当前位置: 首页 > 面试题库 >

继承Java集合接口(Set,Map,List等)的C ++等效项是什么?还是扩展AbstractCollection?

叶琦
2023-03-14
问题内容

我已经从Java背景开始使用C 进行编码(实际上,我曾在大学里学习过C ,但我们从未接触过STL等)。

无论如何,我到了要在各种集合中排列数据的地步,然后我立即告诉自己:“好吧,这是一种Set;这是一个List或ArrayList;这是地图等。”
在Java中,我只要编写任何类即可实现Set或Map或List接口。但是我可能不会继承ArrayList或HashSet之类的东西,或者不那么做,那里的实现涉及某种形式,我不想弄乱它们。

现在,我该如何在C 中使用标准库?似乎没有用于集合,地图,列表等的抽象基类-
等效于Java接口;另一方面,标准容器的实现看起来很糟糕。好的,一旦您了解它们,也许它们并没有那么恐怖,但是假设我只是想编写类似于在C

中扩展AbstractSet的非虚拟类之类的东西?我可以传递给需要Set的任何函数吗?我应该怎么做呢?

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


问题答案:

简短的答案是:没有等效项,因为C ++的处理方式有所不同。

毫无疑问,这就是事实。如果您不喜欢这样,请使用其他语言。

长答案是:有一个等效项,但这会让您有些不满意,因为尽管Java的容器和算法模型很大程度上基于继承,而C 却并非如此。C

模型很大程度上基于通用迭代器。

举个例子,您要实现一个集合。无视事实,C
++已经有std::setstd::multisetstd::unordered_setstd::unordered_multiset
,这些都是定制不同的比较器和分配器,以及无序那些有定制的散列函数,当然。

因此,假设您要重新实现std::set。例如,您可能是计算机科学专业的学生,​​并且想要比较AVL树,2-3棵树,红黑树和八角树。

你会怎么做?你会这样写:

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);

当然,您不必全部编写这些代码,特别是如果您只是编写一些代码来测试其中的一部分。但是,如果您编写了所有这些内容(为了清楚起见,我将其排除在外),那么您将拥有的是功能全面的set类。那个固定类有什么特别之处?

您可以在任何地方使用它。与a搭配使用的任何物品std::set都可以与您的套装搭配使用。不必为此专门编程。它不需要任何东西。任何适用于任何set类型的东西都应该适用于它。Boost的任何算法都可以在场景上使用。

您编写的用于集合的任何算法都可以在集合上使用,并可以增强集合和许多其他集合。但不仅限于现场。如果他们写得不错,他们将在支持特定迭代器类型的任何容器上工作。如果他们需要随机访问,他们将需要RandomAccessIterators,它std::vector提供了,但是std::list没有。如果他们需要BidirectionalIterators,那么std::vectorand
std::list(和其他)将可以正常工作,但std::forward_list不会。

迭代器/算法/容器的工作原理非常好。考虑在C ++中将文件读取为字符串的清洁度:

using namespace std;

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


 类似资料:
  • 本文向大家介绍List,Set, Map是否继承自Collection接口?相关面试题,主要包含被问及List,Set, Map是否继承自Collection接口?时的应答技巧和注意事项,需要的朋友参考一下 答:List,Set是Map不是

  • 我有一个关于继承定义的理论问题。一个月前我参加了一个测试,我们必须举一个遗传的例子。 这是我的答案: 根据定义,extend关键字表示正在定义的类是使用继承从基派生的。然而,我的教授认为这个答案是错误的,因为我的例子是一个接口扩展,与继承无关。 接口扩展和继承有什么区别?为什么我的答案是错误的,我是否混淆了继承的定义?

  • 问题内容: LINQ的Java等效项是什么? 问题答案: 现在使用Java 8向我们介绍了Stream API,这在处理集合时是类似的事情,但与Linq不太一样。 如果它是您正在寻找的ORM,例如Entity Framework,那么您可以尝试Hibernate

  • 问题内容: 请提出与Shell脚本等效的Python命令。 有没有办法打印/记录Python执行的每个源文件行? 问题答案: 您可以使用跟踪模块: 上面的命令行将在执行代码时显示每一行代码。

  • 问题内容: 将Java转换为C#时,将语言环境转换为CultureInfo的正确方法是什么? 我知道在C#中,我们拥有当前线程的文化,并且在某些情况下为了写文件而希望提供一致性。但是Java Locale.ROOT和Locale.getDefault()是什么意思,它们通常如何映射到C#中的选项? 问题答案: 好吧,多亏了Andreas,我可以从javadoc中进行总结: 和 我只是希望该文档更容

  • 问题内容: PHP具有 var_dump()函数,该函数输出对象的内部内容,显示对象的类型和内容。 例如: 将输出: Java中将执行相同操作的等效项是什么? 问题答案: 它不是Java中的嵌入式程序,因此您不会免费获得它。 它是通过约定而不是语言构造完成的。在所有数据传输类中(甚至 在您编写的所有类中…… ),您都应该实现一个明智的方法。因此,这里您需要在您的类中重写并返回所需的状态。 有一些实