【发布时间】:2018-09-09 05:58:56
【问题描述】:
我使用std::set 来存储一个类的唯一实例。 std::set 没有重载的下标运算符,所以你不能做 set[0] 的例子。
我找到了办法:
auto myClass = *std::next(set.begin(), index);
但是,我发现一遍又一遍地复制该代码很单调。所以我决定只扩展std::set (class sset) 并重载其中的下标运算符会更方便。
template <class T>
class sset: public std::set<T>
{
public:
T operator[](const uint32_t i) const
{
if(i <= (this->size()-1))
return *std::next(this->begin(), i);
else
throw std::out_of_range("Index is out of range");
}
};
int main()
{
auto myClass = set[0]; //works and no exception thrown
return 0;
}
我实现了预期的行为,但我突然想到标准没有包含下标运算符一定是有原因的。当然不只是懒惰。
这样做是否有任何预先知道的缺点或未来可能出现的问题?
【问题讨论】:
-
下标重载对于
std::map和std::unordered_map这样的关联类型有意义,因为它模仿数组的行为,只是使用任意键类型而不是整数索引。但是集合不保存键/值对,它们只保存键。someset["a"]应该如何工作?您无法分配给它,因为没有与该键关联的值。它应该返回什么?再次,没有价值......这没有意义。因此,没有下标重载。 -
这是
set,对吧?这意味着容器中的项目没有 fixed 索引。也就是说,set[2]可能只是通过将一个元素插入到集合中而成为不同的对象。那么为什么你需要像这样通过数字索引来索引一个集合呢? -
请注意,C++ 中的容器类并非旨在公开继承。如果您真的想使用这样一个特殊的集合容器(一开始是个坏主意,请参阅所有答案),那么您应该从
std::set私下继承或使用您委托所有必需操作的数据成员。 -
@ChristianHackl:
std::stack和std::queue,带有受保护的成员,显然是为了继承而设计的。我知道当没有虚拟析构函数时,公共继承是禁忌的,这是一种误导的概念。也许这就是你所指的? -
@Cheersandhth.-Alf:是的,我指的是“错误的”概念,即没有虚函数的类通常不应该被公开继承。
标签: c++ class c++11 stdset extending-classes