我已经从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::set
,std::multiset
,std::unordered_set
和std::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::vector
and
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中的嵌入式程序,因此您不会免费获得它。 它是通过约定而不是语言构造完成的。在所有数据传输类中(甚至 在您编写的所有类中…… ),您都应该实现一个明智的方法。因此,这里您需要在您的类中重写并返回所需的状态。 有一些实