给定基类和派生类如下:
基地:
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...
如上所述,为什么在执行第二个print
时调用派生类中定义的r.print()
?
答案 0 :(得分:3)
因为表达式r = bb
完全等同于aa = bb
。赋值运算符仅将bb
类已知的AA
部分复制到aa
对象中。
换句话说,在分配后,r
仍指向aa
,这是AA
的一个实例。在任何意义上它都 not 指向BB
实例。
引用永远不能更改它引用的对象,因此使用引用无法实现预期的行为。为了获得你正在寻找的多态性,你可以使用指针:
AA* p = &aa;
p->print();
p = &bb;
p->print();
答案 1 :(得分:1)
因此:
r = bb;
上述语句不会将引用r
绑定(重新绑定?)到bb
。相反,它会将AA
bb
部分复制到aa
r
,这是{{1}}引用的对象。
为测试上述声明,以下是一个示例:http://coliru.stacked-crooked.com/a/00d20990fe0ddd26