与C++继承混淆

Pet*_*Lee 4 c++ inheritance

我对以下代码的输出很困惑:

#include <iostream>

using namespace std;

class Parent
{
public:
    Parent() : x(2) { }
    virtual ~Parent() { }

    void NonVirtual() { cout << "Parent::NonVirtual() x = " << x << endl; }

private:
    int x;
};

class Child : public Parent
{
public:
    Child() : x(1) { }
    virtual ~Child() { }

    void NonVirtual() { cout << "Child::NonVirtual() x = " << x << endl; }

private:
    int x;
};

int main()
{
    Child c;
    Parent* p = &c;

    c.NonVirtual();  // Output: Child::NonVirtual() x = 1
    p->NonVirtual(); // Output: Parent::NonVirtual() x = 2
    // Question: are there two x'es in the Child object c?
    //           where is x = 2 from (we have not defined any Parent object)?

    cout << sizeof(c) << endl;
    cout << sizeof(*p) << endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Mic*_*yan 5

上面的代码说明了这样一个事实,即在C++中,只有标记virtual的函数才会被覆盖.你在这里拥有的是黯然失色,而不是压倒一切.在重写和继承中,行为基于运行时类型,这是您期望的正常继承行为,但如果您不将其声明为虚拟,那么该行为完全基于编译时类型(即声明的类型).由于p被声明为Parent*类型,它使用Parent中的实现,而c被声明为Child类型,因此它使用Child类型给出的版本.如果您将方法声明为virtual,那么在这两种情况下,它都会在运行时查找该函数的相应版本并调用Child类中给出的版本.

我还应该补充一点,你有两个不同的x变量...如果你想在基类和派生类之间共享变量,你应该在基类中将它标记为"受保护"(尽管我认为它通常很差)设计这样做).您在Child中声明的x变量是与Parent中的变量不同的变量.请记住,x在Parent中是私有的,因此在Child中创建名为x的第二个变量之前,名称x在Child中没有任何意义.

  • 构造Child时,将在Child构造函数之前自动调用Parent类的默认构造函数.这将Parent :: x指定为2.然后调用Child的构造函数将Child :: x设置为1.由于每个类都有自己的x,因此得到的取决于运行时类型. (3认同)