Han*_*Sun 3 c++ oop pointers virtual-functions multiple-inheritance
以下是代码:
#include <iostream>
using namespace std;
class B1 {
public:
virtual void f1() {
cout << "B1\n";
}
};
class B2 {
public:
virtual void f1() {
cout << "B2\n";
}
};
class D : public B1, public B2 {
public:
void f1() {
cout << "OK\n" ;
}
};
int main () {
D dd;
B1 *b1d = ⅆ
B2 *b2d = ⅆ
D *ddd = ⅆ
cout << b1d << endl;
cout << b2d << endl;
cout << ddd << endl;
b1d -> f1();
b2d -> f1();
ddd -> f1();
}
Run Code Online (Sandbox Code Playgroud)
输出是:
0x79ffdf842ee0
0x79ffdf842ee8
0x79ffdf842ee0
OK
OK
OK
Run Code Online (Sandbox Code Playgroud)
这看起来让我感到困惑,因为我期望b1d并且b2d两者都指向相同dd.但是,根据结果,b1d和的值b2d是不同的.我认为这可能与打字有关,但我不确定它是如何工作的.
有没有人有这个想法?
Nat*_*ica 12
D继承自B1和B2.
由于B1从头开始继承,因此首先B1构造B2对象的一部分,然后创建对象的一部分D.
所以你看到的是当你将派生类型的指针强制转换为基类型时,这些部分在内存中的位置的差异.
b1d并且ddd具有相同的地址,因为它们都指向内存中类的开头.
b2d是偏移的,因为它指向B2部分的开头D.
您对此的看法部分正确.该指针指的是对象的地址,当然这是一个类的一部分.为了更正式,这是指向该类的vtable的指针.但是在你从多个类继承的情况下.那么这应该指向什么呢?
说你有这个:
class concrete : public InterfaceA, public InterfaceB
Run Code Online (Sandbox Code Playgroud)
从interfaceA和interfaceB继承的具体对象必须能够像bot interfaceA和interfaceB一样行动(这是公共的重点:当你继承时).所以应该有一个"这个调整",这样就可以做到.
通常,在多重继承的情况下,选择基类(例如,接口).在这种情况下,
几乎每个编译器都有一个"约定"来生成代码.例如,为了调用funa,编译器生成的程序集类似于:
call *(*objA+0)
Run Code Online (Sandbox Code Playgroud)
其中+0部分是vtable内函数的偏移量.
编译器需要在编译时知道此方法的(funa)偏移量.
现在,如果你想打电话,会发生什么?基于我们所说的,funb需要位于interfaceB对象的偏移0处.所以有一个thunk adjustor来调整它,使它指向interfaceB的vtable,这样就可以正常调用funB,同样:
call *(*objB+0)
Run Code Online (Sandbox Code Playgroud)
如果你声明这样的东西:
concrete *ac = new concrete();
interfaceB *ifb = ac;
Run Code Online (Sandbox Code Playgroud)
你能指望什么?具体现在扮演interfaceB的角色:
如果我没记错的话,你可以打印ifb和ac(它们是指针),并验证它们指向不同的地址,但如果你检查它们是否相等:
ifb == ac;
Run Code Online (Sandbox Code Playgroud)
你应该变得正确,因为它们被调整以便描述它们是相同的动态生成的对象.