关于简单c ++继承的解释

时间:2015-06-25 11:32:59

标签: c++ inheritance

#include <iostream>

using namespace std;
class A {
public:
    void m1(){ cout << 'A'; }
    virtual void m2(){ cout << 'B'; }
    virtual void m3(){ cout << 'C'; }
};

class B: public A {
public:
    void m1(){ cout << 'D'; }
    void m2(){ cout << 'E'; }
};

class C: public B {
public:
    void m3(){ cout << 'F'; }
};

int main()
{
    cout << "Hello World!" << endl;
    A* a = new B();
    a->m1();
    a->m2();
    a->m3();
    return 0;
}

输出是什么?我最初认为它将是“D E C”,但在运行程序后它是“A E C”

可以详细说明这行代码背后的内容:

A* a = new B();

5 个答案:

答案 0 :(得分:6)

根据对象的动态(运行时)类型调度虚拟成员函数。根据对象的 static (编译时)类型调度非虚拟成员函数。

A *a = new B();

a指向动态类型为B的对象。然而,a的静态类型为A*,这意味着*a的静态类型为A

根据动态类型调度虚拟函数(m2m3),因此调用B::m2B::m3

根据静态类型调度非虚函数。 *a的静态类型为A,因此调用A::m1

new行究竟发生了什么?类型为B的新对象是动态创建的,new表达式返回指向该对象的指针(类型为B*)。然后,对该指针应用派生到基础的转换,将其转换为A*,用于初始化变量a

在伪代码中,显示中间步骤:

B *tmp_b = new B(); // allocate and initialise B object
A *tmp_a = convert_derived_to_base(tmp_b);
A *a = tmp_a;

答案 1 :(得分:1)

m1方法在A类中不是虚拟的,它不能被覆盖.m2是虚拟的,所以它用B类方法覆盖。

答案 2 :(得分:1)

输出

AEC

原因是A::m1未声明virtual。在这一行

A* a = new B();

您正在声明名为A*的{​​{1}}变量,该变量实际上是派生类a的一个实例。这是允许的,因为“B是一种B”。

当函数声明为A时,如果派生类定义了该函数,那么基类中的函数将被派生类中的版本覆盖。因此,将进行以下调用

virtual

答案 3 :(得分:0)

此处Class A是您的父类,因此要覆盖父类的方法,您需要在A类中将其设为virtual。以便Class B&#39; s方法将被调用。请参阅Virtual Functions

的更多信息

答案 4 :(得分:0)

void m1(){ cout << 'A'; }
virtual void m2(){ cout << 'B'; }
virtual void m3(){ cout << 'C'; }

根据您的程序代码,输出完全正常。

void m1(){ cout << 'A';不是虚函数。 因此,a->m1();会调用m1的基本版本,并将o / p称为A

m2()是一个虚函数,它在B类中有一个新的实现。 void m2(){ cout << 'E'; }

因此a->m2();调用class B函数的m2版本并输出E

m3内没有class B的新实现。 因此a->m3();调用从m3继承的class A

要将o / p设为DEC,您只需将m1函数更改为虚拟函数,如下所示

class A { public: virtual void m1(){ cout << 'A'; } virtual void m2(){ cout << 'B'; } virtual void m3(){ cout << 'C'; } };