我确认了@BЈовић 和@NIRAJ RATHI 指出的切片问题,
然后我注意到可以使用引用在抽象基类中调用公共赋值运算符的情况。这是可能的,但可能会导致切片问题。因此,需要将赋值运算符设为虚拟,在子类中覆盖它并向下转换。
#include <stdio.h>
class X {
public:
int x;
X(int inx): x(inx) {}
virtual void doSomething() = 0;
virtual void print() { printf("X(%d)\n",x); }
virtual X& operator=(const X& rhs) {
printf("X& X::operator=() \n");
x = rhs.x;
return *this;
}
};
class Y : public X {
public:
int y;
Y(int inx,int iny) : X(inx), y(iny) {}
void doSomething() { printf("Hi, I'm Y."); }
virtual void print() { printf("Y(%d,%d)\n",x,y); }
virtual X& operator=(const X& rhs);
};
X& Y::operator=(const X& rhs) {
printf("X& Y::operator=() \n");
const Y& obj = dynamic_cast<const Y&>(rhs);
X::operator=(rhs);
y = obj.y;
return *this;
}
int main()
{
Y a(1,2);
Y a2(3,4);
X& r = a;
r = a2; // calling assignment operator on ABC without slicing!!
r.print();
}
在我的结论中:
- 可以通过使用引用在抽象基类中调用赋值运算符。
- 规则 12-8-2 旨在防止切片问题。
- 如果没有切片问题,我不必总是应用规则 12-8-2。