【问题标题】:Child Class to Base Class Conversion Issue [duplicate]子类到基类的转换问题[重复]
【发布时间】:2013-08-03 18:07:21
【问题描述】:

我已经声明了一个具有虚拟打印功能的超类,而子类继承了超类。我创建了一个子类实例并以两种不同的方式分配给超类。

#include <iostream>

using namespace std;

class Super
{
public:
    Super(){}
    virtual void print()
    {
    cout << "Super class is printing " << endl;
    }
};

class Child: public Super
{
public:
    Child(){}
    void print()
    {
        cout << "Child class printing" << endl;
    }
};

int main()
{
    Child c;
    Super s = c;
    Super &ss = c;
    s.print(); //prints "Super Class is printing
    ss.print(); //prints "Child Class is printing
    return 0;
}

为什么我们没有从这两个打印调用中得到相同的输出?添加引用如何改变行为?

【问题讨论】:

标签: c++ virtual


【解决方案1】:

s 的动态静态类型是Super,但来自c 的赋值从cs 内部复制了Super 子对象作为Super

但是,ss 有一个静态类型 Super,但它的动态类型取决于它的初始化,在本例中为 Child,因此虚拟调度会相应地运行。

这种现象称为"object slicing"

【讨论】:

    【解决方案2】:

    对象切片问题:

    如果你获取一个超类并为其分配子类的值,则只有属于超类的成员会被复制(默认赋值运算符行为)。

    考虑以下几点:

    #include <iostream>
    
    using namespace std;
    
    class Super {
    public:
       int a;
       Super(): a(0) { }
       Super(int _a): a(_a) { }
       virtual void dump() {
            cout << "A is : " << a << std::endl;
       }
    };
    
    class Child: public Super {
    public: 
       int b;
    
       Child(int _a, int _b): b(_b), Super(_a) { } 
       virtual void dump() {
            Super::dump();
            cout << "B is : " << b << std::endl;
       }
    
    };
    
    int main() {
        Child c(5, 10);
        Super s;
        s.dump();  // A is 0
        s = c;
        s.dump();  // A is 5 (but there is no B in s 
                   // so calling Child::dump would be nonsensical
    }
    

    所以你可以看到,当子值被分配给父值时,调用子dump 是没有意义的;因为父上下文中没有“b”。

    请注意以下语句: c = s;

    是没有意义的,因为虽然父系是确定性的(Child 是 Super 的类型,所以隐式运算符 Super&amp; Super::operator=(const Super&amp;) 适用于派生的 Child 类,反之则不正确;即 Child&amp; Child::operator=(const Child&amp;)Super的上下文

    参考问题

    好的,所以混淆来自于理解什么是引用变量。引用变量是任何它初始化的同义词。您可以像使用原始变量一样使用引用变量。

    在你的情况下:

       ss.print(); 
    

    一样
       c.print();
    

    " 要更清楚地看到这一点,请考虑以下 sn-p:

    int foo;
    int& bar = foo;
    
    // bar is now a reference to foo so the following will sets foo to 67
    bar = 67;
    std::cout << foo <<std::endl;
    

    【讨论】:

    • 有点迂腐:“引用变量是分配给它的任何东西的同义词”不,无论你用什么初始化它。它与实际的 assignment 无关,即使它可能使用 = 就像在您的示例中一样。其他一些初始化引用的方法:int&amp; bar{foo}; (C++11) 和 int&amp; bar(foo)
    • 对创建引用的过程的一个更好的术语是绑定,然后可以谈论它绑定到的对象
    • @DyP Nuanced :-) 我会修复答案。
    猜你喜欢
    • 1970-01-01
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-22
    • 2012-09-15
    • 1970-01-01
    相关资源
    最近更新 更多