继承Java集合接口(Set,Map,List等)的C ++等价物是什么?或者扩展AbstractCollection? [英] What is the C++ equivalent of inheriting a Java collection interface (Set, Map, List etc.)? Or extending AbstractCollection?

查看:115
本文介绍了继承Java集合接口(Set,Map,List等)的C ++等价物是什么?或者扩展AbstractCollection?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经开始使用C ++进行编码,来自Java背景(实际上我在我的大学学过C ++,但我们从未进入过STL等。)

I've started coding in C++, coming from a Java background (actually I'd studied C++ at my university, but we never got to the STL etc.)

无论如何,我已经到了我在各种集合中安排数据的地步,我立刻告诉自己好吧,这是一种Set;这是一个List,或者一个ArrayList;并且这是一张地图等。在Java中,我只想让我正在编写的任何类实现Set或Map或List接口;但是我可能不会继续继承ArrayList或HashSet或者什么不是,那里的实现有点涉及,我不想搞砸它们。

Anyway, I've gotten to the point where I'm arranging data in all sorts of collections, and I immediately tell myself "Ok, this is a kind of a Set; and this is a List, or an ArrayList; and this is a map etc." In Java, I would simply have whatever class I'm writing implement the Set or Map or List interface; but I would probably not go as far as inheriting ArrayList or HashSet or what-not, the implementations there are kind of involved and I wouldn't want to mess them up.

现在,我在C ++中做什么(使用标准库)?似乎没有集合,映射,列表等的抽象基类 - 相当于Java接口;另一方面,标准容器的实现看起来非常可怕。好吧,也许他们一旦你了解它们就不那么可怕了,但是假设我只是想写一些类似于在C ++中扩展AbstractSet的非虚拟类?我可以传递给任何需要Set的函数吗?我应该怎么做呢?

Now, what do I do in C++ (with the Standard Library)? There do not seem to be abstract base classes for Sets, Maps, Lists etc - the equivalent of Java interfaces; on the other hand, the implementations for the standard containers look pretty horrid. Ok, maybe they're not so horrid once you get to know them, but suppose I just wanted to write something like a non-virtual class extending AbstractSet in C++? Something I would be able to pass to any function which takes a Set? How should I go about doing that?

只是为了澄清 - 我不一定想做Java中的常见做法。但是,另一方面,如果我有一个对象,从概念上讲,它是一种集合,我想继承适当的东西,免费获得默认实现,并由我的IDE指导实现我应该实现的那些方法。 / p>

Just to clarify - I don't necessarily want to do what's common practice in Java. But, on the other hand, if I have an object which, conceptually, is a kind of set, I want to inherit something appropriate, get default implementations gratis, and be guided by my IDE to implement those methods which I should implement.

推荐答案

简短的回答是:没有等效的,因为C ++做的事情不同。

没有必要争论这个问题,这只是事情的方式。如果您不喜欢这样,请使用其他语言。

There's no point arguing about this, it's just the way things are. If you don't like this, use a different language.

答案很长:有一个等价物,但它会让你有点不高兴,因为虽然Java的容器和算法的模型主要基于继承,而C ++则不然。 C ++的模型主要基于泛型迭代器。

The long answer is: there is an equivalent but it's going to make you a little unhappy, because while Java's model of containers and algorithms is heavily based around inheritance, C++'s isn't. C++'s model is heavily based around generic iterators.

假设您想要实现一个集合。忽略C ++已经 std :: set std :: multiset std这一事实:: unordered_set std :: unordered_multiset 这些都是可以使用不同的比较器和分配器自定义的,以及当然,无序的哈希函数具有可自定义的哈希函数。

Let's say, to take your example, that you want to implement a set. Ignoring the fact that C++ already has std::set, std::multiset, std::unordered_set and std::unordered_multiset, and that these are all customisable with different comparators and allocators, and the unordered ones have customisable hash functions, of course.

因此,假设你要重新实现 std :: set 。也许你是一名计算机科学专业的学生,​​你想要比较AVL树,2-3棵树,红黑树和树枝树。

So let's say you want to reimplement std::set. Perhaps you're a computer science student and you want to compare AVL trees, 2-3 trees, red-black trees and splay trees, for example.

你会怎么做?你会写:

template<class Key, class Compare = std::less<Key>, class Allocator = std::allocator<Key>> 
class set {
    using key_type = Key;
    using value_type = Key;
    using size_type = std::size_t;
    using difference_type = std::ptrdiff_t;
    using key_compare = Compare;
    using value_compare = Compare;
    using allocator_type = Allocator;
    using reference = value_type&;
    using const_reference = const value_type&;
    using pointer = std::allocator_traits<Allocator>::pointer;
    using const_pointer = std::allocator_traits<Allocator>::const_pointer;
    using iterator = /* depends on your implementation */;
    using const_iterator = /* depends on your implementation */;
    using reverse_iterator = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>

    iterator begin() const;
    iterator end() const;
    const_iterator cbegin() const;
    const_iterator cend() const;
    reverse_iterator rbegin() const;
    reverse_iterator rend() const;
    const_reverse_iterator crbegin() const;
    const_reverse_iterator crend() const;

    bool empty() const;
    size_type size() const;
    size_type max_size() const;

    void clear();

    std::pair<iterator, bool> insert(const value_type& value);
    std::pair<iterator, bool> insert(value_type&& value);
    iterator insert(const_iterator hint, const value_type& value);
    iterator insert(const_iterator hint, value_type&& value);
    template <typename InputIterator>
    void insert(InputIterator first, InputIterator last);
    void insert(std::initializer_list<value_type> ilist);

    template <class ...Args>
    std::pair<iterator, bool> emplace(Args&&... args);

    void erase(iterator pos);
    iterator erase(const_iterator pos);
    void erase(iterator first, iterator last);
    iterator erase(const_iterator first, const_iterator last);
    size_type erase(const key_type& key);

    void swap(set& other);

    size_type count(const Key& key) const;
    iterator find(const Key& key);
    const_iterator find(const Key& key) const;

    std::pair<iterator, iterator> equal_range(const Key& key);
    std::pair<const_iterator, const_iterator> equal_range(const Key& key) const;

    iterator lower_bound(const Key& key);
    const_iterator lower_bound(const Key& key) const;
    iterator upper_bound(const Key& key);
    const_iterator upper_bound(const Key& key) const;

    key_compare key_comp() const;
    value_compare value_comp() const;
}; // offtopic: don't forget the ; if you've come from Java!

template<class Key, class Compare, class Alloc>
void swap(set<Key,Compare,Alloc>& lhs, 
          set<Key,Compare,Alloc>& rhs);

template <class Key, class Compare, class Alloc>
bool operator==(const set<Key,Compare,Alloc>& lhs,
                const set<Key,Compare,Alloc>& rhs);

template <class Key, class Compare, class Alloc>
bool operator!=(const set<Key,Compare,Alloc>& lhs,
                const set<Key,Compare,Alloc>& rhs);

template <class Key, class Compare, class Alloc>
bool operator<(const set<Key,Compare,Alloc>& lhs,
               const set<Key,Compare,Alloc>& rhs);

template <class Key, class Compare, class Alloc>
bool operator<=(const set<Key,Compare,Alloc>& lhs,
                const set<Key,Compare,Alloc>& rhs);

template <class Key, class Compare, class Alloc>
bool operator>(const set<Key,Compare,Alloc>& lhs,
               const set<Key,Compare,Alloc>& rhs);

template <class Key, class Compare, class Alloc>
bool operator>=(const set<Key,Compare,Alloc>& lhs,
                const set<Key,Compare,Alloc>& rhs);

当然你不必写所有这些,特别是如果你只是写一些东西测试它们的一部分。但是如果你写下所有这些(为了清晰起见,我会将其排除在外),那么你所拥有的将是一个功能齐全的集合类。那个集合类有什么特别之处?

Of course you don't have to write ALL of those, especially if you're just writing something to test parts of them. But if you write all that (and a little bit more I excluded for clarity), then what you will have will be a fully functioning set class. And what is special about that set class?

你可以在任何地方使用它。任何适用于 std :: set 的东西都可以使用你的套装。它不必专门为它编程。它不需要任何东西。任何适用于任何集合类型的东西都应该适用于它。 Boost的任何算法都可以在集合上运行。

You can use it anywhere. Anything that works with a std::set will work with your set. It doesn't have to be programmed specially for it. It doesn't need anything. And anything that works on ANY set type should work on it. And any of Boost's algorithms will work on sets.

你编写的任何算法都可以在你的集合和boost集合以及许多其他集合上运行。但不只是集合。如果它们被正确编写,它们将在任何支持特定类型迭代器的容器上工作。如果他们需要随机访问,他们将需要RandomAccessIterators, std :: vector 提供,但 std :: list 不T。如果他们需要BidirectionalIterators,那么 std :: vector std :: list (和其他人)将正常工作,但 std :: forward_list 不会。

And any algorithms you write to use on sets will work on your sets and boost's sets and lots of other sets. But not just on sets. If they're written competently they'll work on any container that supports a particular type of iterator. If they need random access they'll require RandomAccessIterators, which std::vector provides, but std::list doesn't. If they need BidirectionalIterators, then std::vector and std::list (and others) will work fine, but std::forward_list won't.

迭代器/算法/容器的功能非常好。考虑在C ++中将文件读入字符串的清洁度:

The iterator/algorithm/container thing works really well. Consider the cleanliness of reading a file into a string in C++:

using namespace std;

ifstream file("file.txt");
string file_contents(istreambuf_iterator<char>(file),
                     istreambuf_iterator<char>{});

这篇关于继承Java集合接口(Set,Map,List等)的C ++等价物是什么?或者扩展AbstractCollection?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆