在考虑“继承”时

时间:2013-09-11 00:56:18

标签: c++ pointers inheritance reference

我的遗产不是很流利。我明白,如果你有A级和A级B B可以从封装到A中的代码继承,但就这个问题而言 - 我不确定代码到底在说什么。

问题是:假设你有两个类,A和B. B继承自A.只定义了两个方法,foo()(声明为虚拟)和bar()(不是虚拟的) )。两种方法都将字母A输出到控制台。 B还定义了foo()和bar(),两者都将字母B输出到控制台。

以下代码的输出是什么?

    B b;
    A * pA = new A;
    A * pA2 = &b;
    b.foo(); b.bar();
    pA ->foo(); pA->bar();
    pA2->foo(); pA2->bar();

首先,他们究竟是什么意思“一个是虚拟的,一个不是”。 第二个问题,pA来自哪里?他们在这做什么?与pA2相同的是什么?它在问题中从未提及过pA或pA2。最后,& b是一个参考变量?

感谢您的时间。

1 个答案:

答案 0 :(得分:2)

使用指针或引用时,变量有两种类型:动态类型和静态类型。静态类型是您静态赋予该变量的指针类型(在编译时已知),而动态类型是它指向的对象的指针类型。

例如,假设DogAnimal的子类:

Animal* p = new Dog;

p的静态类型为Animal*,动态类型为Dog*。在处理runtime type identification (RTTI)时,这一点非常重要。

好的,让我们一步一步地分析代码:

B b;
A * pA = new A;
A * pA2 = &b;

我们将b作为静态类型BpA,其A*pA2的静态和动态类型的静态类型为A*,但B*的动态类型(请参阅virtual tablesb.foo(); b.bar(); 1}}。

b

现在B正在调用它的两个方法。两者都将pA->foo(); pA->bar(); 打印到屏幕上(就像你通常所期望的那样(因为B的函数定义隐藏 A)。

A

以上几乎几乎相同。他们都打印A*,因为他们的静态和动态类型为A,他们的定义表明他们应该打印pA2->foo(); pA2->bar();

pA2

这可能是所有这一切中最令人困惑的部分。我们说A*的静态类型为B* ,但是动态类型foo。这是什么意思?

这意味着在查找B*的函数定义时,它实际上会查看虚拟表并找出其动态类型的定义(B),print { {1}}。

虽然第二次调用非虚拟方法,因此没有“函数虚拟查找表”:方法的定义取自其静态类型({{1打印A*

final output是:

A