给定基类和派生类如下:
底座:
class AA
{
public:
AA() = default;
virtual void print() const { std::cout << aa << "n";}
private:
std::string aa = "AA";
};
派生的:
class BB : public AA
{
public:
BB() = default;
virtual void print() const override {std::cout << bb << "n"; }
private:
std::string bb = "BB";
};
第一次尝试:
int main()
{
AA aa; BB bb;
AA& //r = aa; r.print();
r = bb;
r.print();
return 0;
}
结果完全符合我的预期:
BB
Press <RETURN> to close this window...
但是删除//
时的第二次尝试:
int main()
{
AA aa; BB bb;
AA& r = aa; r.print();
r = bb;
r.print();
//!^^^^^^^^^^--why wasn't the print in derived class called?
return 0;
}
输出为:
AA
AA
Press <RETURN> to close this window...
如上所述,为什么在执行第二个r.print()
时没有调用派生类中定义的print
?
因为表达式r = bb
完全等同于aa = bb
。赋值运算符只是将AA
类已知的bb
部分复制到aa
对象中。
换句话说,在赋值之后,r
仍然指向aa
,这是AA
的一个实例。它在任何意义上都不指向BB
实例。
引用永远无法更改它引用的对象,因此无法使用引用实现预期的行为。为了获得您正在寻找的多态性,您需要使用指针:
AA* p = &aa;
p->print();
p = &bb;
p->print();
因为这个:
r = bb;
上述语句不绑定(重新绑定?)引用r
bb
。相反,它将bb
的AA
部分复制到aa
即r
引用的对象。
为了测试上述说法,这里有一个例子:http://coliru.stacked-crooked.com/a/00d20990fe0ddd26