Ber*_*ard 7 c++ inheritance siblings c++17
为了代码重用的目的,我有许多派生自同一个基础的结构,但我不想要任何形式的多态.
struct B {
int field;
void doStuff() {}
bool operator==(const B& b) {
return field == b.field;
}
};
struct D1 : public B {
D1(int field) : B{field} {}
};
struct D2 : public B {
D2(int field) : B{field} {}
};
Run Code Online (Sandbox Code Playgroud)
结构D1
和D2
(以及更类似的结构)派生自B
共享公共字段和方法,因此我不需要在每个派生类中复制这些字段和方法.
结构B
永远不会被实例化; 我只使用D1
和的实例D2
.此外,D1
并且D2
根本不应该彼此互动.从本质上讲,我不希望任何多态行为:D1
并且D2
,出于所有目的,应该充当不相关的结构.
我希望任何D1
与其他D1
s 相比较的平等,以及任何D2
与其他D2
s 相比较的平等.由于D1
并且D2
不包含任何字段,因此在struct中定义相等运算符似乎是合适的B
.
但是,(正如预期的那样)我D1
和之间进行了以下互动D2
:
int main() {
D1 d1a(1);
D1 d1b(1);
D2 d2(1);
assert(d1a == d1b); // good
assert(d1a == d2); // oh no, it compiles!
}
Run Code Online (Sandbox Code Playgroud)
我不希望能够D1
与D2
对象进行比较,因为出于所有目的,它们应该表现得与它们无关.
如何在不重复代码的情况下使最后一个断言成为编译错误?分别定义等号操作符D1
和D2
(和所有其他类似结构)将意味着代码的重复,所以我想避免,如果可能的.
"结构D1和D2(以及更相似的结构)来自B,以分享共同的领域和方法"
然后做B
一个private
基类.显然,D1
并且D2
不应该共享它们的相等运算符,因为这两个运算符采用不同的参数.您当然可以共享部分实现bool B::equal(B const&) const
,因为外部用户无法访问.
您可以使用CRTPoperator ==
仅在对最终类型的基类的引用上定义:
template<typename T>
struct B {
int field;
void doStuff() {}
bool operator==(const B<T>& b) {
return field == b.field;
}
};
struct D1 : public B<D1> {
D1(int field) : B{field} {}
};
struct D2 : public B<D2> {
D2(int field) : B{field} {}
};
Run Code Online (Sandbox Code Playgroud)
这会导致第一个assert
编译,而第二个被拒绝。