0

我对继承不是很流利。我知道,如果你有 Class A & B,B 可以从封装到 A 中的代码继承,但就这个问题而言 - 我不确定代码到底在说什么。

问题是:假设你有两个类,A 和 B。B 继承自 A。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 是参考变量吗?

感谢您的时间。

4

1 回答 1

2

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

例如假设Dog是一个子类Animal

Animal* p = new Dog;

p有一个静态类型Animal*和一个动态类型Dog*。这在处理运行时类型标识 (RTTI) 时最为重要。

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

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

这里我们有bB作为静态类型。pA它具有 的静态和动态类型,A*并且pA2具有 的静态类型,A*但具有 的动态类型(请参阅虚拟表B*

b.foo(); 
b.bar();

现在b正在调用它的两个方法。两者都打印B到屏幕上(就像您通常期望的那样(因为 B 的函数定义隐藏了 A)。

pA->foo(); 
pA->bar();

上述行几乎相同。它们都 printA因为它们的 static 和 dynamic 类型是A*并且它们的定义说它们应该 print A

pA2->foo(); 
pA2->bar();

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

意思就是在查找的函数定义的foo时候,其实是会看一下虚表,找出它的动态类型(也就是B*)的定义,printing B

虽然第二次调用是对非虚拟方法进行的,因此没有“函数虚拟查找表”:该方法的定义取自其静态类型(即A*)printing A

最终输出为:

B B A A B A
于 2013-09-11T01:42:07.623 回答