为从 std::vector 派生的类正确重载双等号
Posted
技术标签:
【中文标题】为从 std::vector 派生的类正确重载双等号【英文标题】:Properly overload double equals for a class deriving from std::vector 【发布时间】:2012-06-15 15:03:37 【问题描述】:我有课
class Item
int _one;
int _two;
int _three;
// other stuff
;
class ItemList : public std::vector<Item>
// deriving from std vector because the ctor needs to
// perform some work in discriminating what gets added
// to the list
;
我已经阅读了许多反对从 std::vector 派生的论点,我想我会没事的,因为这个类不是派生自。我在 python 中公开这个,使用 boost 矢量索引套件,作为 python 列表。因为我需要构造函数在构造过程中从列表中删除某些元素,所以我决定走这条路线,而不是做我在项目其他地方所做的事情:
class AnotherItem
// class definition
;
typedef std::vector<AnotherItem> AnotherItemList
然后使用 typedef 使用 boost 向量索引套件公开列表。一切似乎都很好,除了我有这个错误:错误 2 错误 C2678: binary '==' : no operator found which take a left-hand operand of type 'Item' (或没有可接受的转换)
错误不是来自 boost 库,而是来自 std 算法代码。我尝试添加自己的类重载 == 运算符,但这并没有解决问题。它看起来像这样:
class Item
// earlier stuff
bool operator==(Item& rhs)
return (_one == rhs._one && _two == rhs._two && _three == rhs._three);
bool operator!=(Item& rhs)
return !(*this == rhs);
;
这并没有解决问题。我错过了什么?此链接here 表明向量的 == 运算符不是成员函数。我尝试在“全局”级别重载(即不在命名空间内),但这也无济于事。那么,我错过了什么?
谢谢, 安迪
【问题讨论】:
您的第一个问题是来自std::vector
... 不要从非设计为继承的类型继承。而是使用组合(即在内部存储 std::vector
)。
您应该使 operator==
和 operator!=
const 正确。 (即bool operator == (const Item& rhs) const ...
)
除了通常从矢量问题继承之外,错误是否告诉您 RHS 的预期内容?它是否给出了任何接近的匹配项?
听起来你是从向量派生来对Item
施加一些约束。 Item
是否有任何合理的可能性自行执行这些约束?
我提到我已经看到支持/反对派生自 std::vector 的论点。 (在“for”阵营中提出的一些论点来自 Stack Overflow 的一些线程。)我创建的列表类不应该继承自,所以我不认为 std::vector 中缺少虚拟析构函数 将是一个问题。 @Jerry 我之前没有考虑过你的评论。我必须考虑更多,但我想我可能只能在 ctor 类中添加约束。
【参考方案1】:
== 的正确重载是
class Item
...
bool operator==(const Item& rhs) const
....
bool operator!=(const Item& rhs) const
return !(*this==rhs);
;
另外,请注意,因为std::vector
没有虚拟成员,所以您的派生ItelmList
不能多态地用于std::vector
本身,特别是不要对std::vector* 调用delete。
我必须这样说,否则我和你将注定要被 C++ 社区毁灭,尽管在 30 多年的编程经验中我从来没有从来没有 从来没有 看到了 std::vector* 或 std::string*。 (因此我真的不知道派生 std 类的所有“恐惧”是关于:只需知道你在做什么并让其他人知道)
【讨论】:
您从未见过std::vector*
或std::string*
?显然你没有花任何时间在这里阅读关于 SO 的菜鸟 C++ 问题 ;-)
@Rook: :-))) +1 ! -BTW- 新手犯错很正常。什么不是,是防止他们。在我了解 == 和 = 之间的区别后,我停止编写“yoda 比较”(例如 if(0==a)...)。在了解了 virtual 和 not 之间的区别之后,我停止了非虚拟 dtors 的厄运。
看起来我遇到了 const 问题。我已经重新编码了我遵循这种模式和构建的东西。不过,仍在考虑这样做的智慧。尽管我的代码现在可以构建,但考虑到从 std::vector 派生的非常严肃的考虑,我不确定它是否会保持这种状态。这个类永远不应该派生自。再一次,有人告诉我,我也永远不需要超过 640k 的 RAM。以上是关于为从 std::vector 派生的类正确重载双等号的主要内容,如果未能解决你的问题,请参考以下文章
C++:当包含从类模板派生的类的标头时,编译器警告 C4505
c++基类对象的std::vector----派生类的运行方法