我与一位同事讨论了将抽象基类标记为不可复制的问题。我没有看到对此的需要,因为基类是抽象的,因此我们不能有base的实例,因此复制基础引用不是问题。派生类可以自行决定是否允许复制。 但是,我的同事向我展示了一个基础参考文献的分配,让我感到非常惊讶。
#include <stdio.h>
struct B
{
virtual void foo() = 0;
virtual ~B(){}
};
struct D : public B
{
D(int i): data(i){}
void foo() override {printf("%d", data);}
int data;
D& operator=(D) = delete;
D(const D&) = delete;
};
int main()
{
D d(1);
D d2(2);
d.foo();
d2.foo();
B& b = d;
B& b2 = d2;
b.foo();
b2.foo();
b = b2; // what is this doing?
b.foo();
b2.foo();
d.foo();
d2.foo();
}
上面的代码输出:12121212
。我真的不明白这里发生了什么。 b = b2;
做了什么?我在这里期待编译错误。
答案 0 :(得分:3)
您没有定义复制赋值运算符,因此默认为您。
默认值不是virtual
,因此它会将B
d2
子对象的任何成员变量复制到B
d
子对象1}}。 (B::operator=
对D::operator=
)一无所知。
像这样使用基类operator=
会破坏一般情况下的封装;虽然在这种情况下,因为B
没有成员变量而且没有基类,所以这一行实际上没有效果。
因此,将B
标记为不可复制可能过于防御;因为它会强制你做的任何后代类想要复制以跳过箍重新启用复制。