【问题标题】:Why didn't the dynamic binding behave as expected?为什么动态绑定没有按预期运行?
【发布时间】:2014-01-22 08:52:09
【问题描述】:

给定基类和派生类如下:

基地:

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

【问题讨论】:

    标签: c++ inheritance dynamic-binding


    【解决方案1】:

    因为表达式r = bb 完全等价于aa = bb。赋值运算符只是将AA 类已知的bb 部分复制到aa 对象中。

    也就是说,赋值后r仍然指向aa,这是AA的一个实例。它确实在任何意义上都指向BB 实例。

    引用永远不能改变它所引用的对象,因此无法通过引用实现预期的行为。要获得您正在寻找的多态性,您可以使用指针:

    AA* p = &aa;
    p->print();
    
    p = &bb;
    p->print();
    

    【讨论】:

    • 所以实际上声明r = bb已经通过将对象bb的子对象复制到它来改变aa的值,不是吗?
    • 我不确定我是否遵循“客体的主体”术语,但是是的:r = bb 只是运行aa.AA::operator=(bb),然后将AA-parts 的bb 复制到AA.
    • 对不起我的愚蠢拼写,我应该写为子对象..不知道为什么我不能以你的名字命名 user4815162342..
    • @Alan.W 您无法向我添加通知,因为这是不必要的 - 因为您正在评论我的回答,所以我会自动收到通知。
    • 这就是为什么当一个类被设计为用作基础时,你通常会禁用分配。
    【解决方案2】:

    因为这个:

    r = bb;
    

    上述语句不会将引用r 绑定(重新绑定?)bb。相反,它将bbAA 部分复制到aa,这是r 引用的对象。

    为了测试上述声明,这里是一个例子:http://coliru.stacked-crooked.com/a/00d20990fe0ddd26

    【讨论】:

    • @Alan.W 这是c++ 中的“标准”在线编译器,尽管您可以在C++ wiki page 中找到更多信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-01
    • 1970-01-01
    相关资源
    最近更新 更多