我在C ++运营商中有点迷失。我想为两个不同的类强制执行赋值运算符,即可以将一个赋值给另一个:
class A {
public:
virtual A &operator =(const A &a) = 0;
};
class B : public A {
public:
virtual A &operator =(const A &a) override {
std::cout << "B" << std::endl;
return *this;
}
};
class C : public A {
public:
virtual A &operator =(const A &a) override {
std::cout << "C" << std::endl;
return *this;
}
};
int main(int argc, char *argv[])
{
B b;
C c;
b = c;
// leads to a linker error: undefined reference to `A::operator=(A const&)'
//B b2;
//b = b2;
}
第一项任务似乎完成了工作,&#34; B&#34;叫做。同样,对于&#34; c = b&#34;,&#34; C&#34;叫做。但是,当我取消注释第二部分时,我收到链接器错误。如果我定义A的运算符,如:
virtual A &operator =(const A &a) {
std::cout << "A" << std::endl;
return *this;
}
我得到&#34; B&#34;,&#34; A&#34;。咦?有人可以解释为什么&#34; A&#34;当分配两个B时需要,但是当B < - C是?
时不需要答案 0 :(得分:2)
编译器生成一个隐式复制赋值运算符,当您执行B = B赋值时,该运算符被选中。执行B = C分配时,不会选择此选项。
http://en.cppreference.com/w/cpp/language/copy_assignment
https://wandbox.org/permlink/CM5tQU656rnwtrKl
如果您查看错误消息:
/tmp/cctHhd0D.o: In function `B::operator=(B const&)':
prog.cc:(.text._ZN1BaSERKS_[_ZN1BaSERKS_]+0x1f): undefined reference to `A::operator=(A const&)'
collect2: error: ld returned 1 exit status
您可以看到链接器错误来自B::operator=(B const&)
内部,因为您没有定义它,意味着它必须是自动生成的。
答案 1 :(得分:2)
当您指定b = b2;
时,它会尝试调用B的默认(隐式)赋值。
默认赋值将调用基类的默认赋值,因此它最终将调用A::operator=(const A &a)
,这是纯虚拟的。
所以你得到链接错误。
答案 2 :(得分:1)
根据标准覆盖派生类中基类的虚拟赋值运算符,不会阻止生成在您的情况下调用的默认复制赋值运算符。类B
的此默认复制赋值运算符将直接调用类A
的复制赋值运算符,因此会出现undefined reference
错误。
13.5.3作业[over.ass]
2任何赋值运算符,甚至是复制和移动赋值运算符,都可以是虚拟的。 [注意:对于已声明虚拟副本/移动分配的基类B的派生类D,D中的复制/移动赋值运算符不会覆盖B的虚拟副本/移动赋值运算符。 [实施例:
struct B {
virtual int operator= (int);
virtual B& operator= (const B&);
};
struct D : B {
virtual int operator= (int);
virtual D& operator= (const B&);
};
D dobj1;
D dobj2;
B* bptr = &dobj1;
void f()
{
bptr->operator=(99); // calls D::operator=(int)
*bptr = 99; // ditto
bptr->operator=(dobj2); // calls D::operator=(const B&)
*bptr = dobj2; // ditto
dobj1 = dobj2; // calls implicitly-declared D::operator=(const D&)
}