我的遗产不是很流利。我明白,如果你有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是一个参考变量?
感谢您的时间。
答案 0 :(得分:2)
使用指针或引用时,变量有两种类型:动态类型和静态类型。静态类型是您静态赋予该变量的指针类型(在编译时已知),而动态类型是它指向的对象的指针类型。
例如,假设Dog
是Animal
的子类:
Animal* p = new Dog;
p
的静态类型为Animal*
,动态类型为Dog*
。在处理runtime type identification (RTTI)时,这一点非常重要。
好的,让我们一步一步地分析代码:
B b;
A * pA = new A;
A * pA2 = &b;
我们将b
作为静态类型B
。 pA
,其A*
和pA2
的静态和动态类型的静态类型为A*
,但B*
的动态类型(请参阅virtual tables)b.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*
。
A