C++ 派生类中的基指针地址是多少?

C++ 派生类中的基指针地址是多少?,c++,pointers,inheritance,memory,C++,Pointers,Inheritance,Memory,据我所知,我们可以使用基类指针来寻址并在派生类中调用虚拟函数,因为基类指针的指针范围更为有限。但我只想知道,基类指针如何知道在派生类中从何处开始 例如,对于记录A、B和C都有自己的数据成员,我们可以在两个不同的类别1中讨论这个问题。A、 B&C都有其虚拟功能;2.A、 B&C只有自己的数据成员,没有任何虚拟功能 A类{…}; B类{…}; C类:公共A、公共B{…}; C C; B*B=&c 在C中,A应该放在B的顶部,那么指针B如何知道在C中从哪里开始寻址呢?编译器知道布局,所以它将发出代码

据我所知,我们可以使用基类指针来寻址并在派生类中调用虚拟函数,因为基类指针的指针范围更为有限。但我只想知道,基类指针如何知道在派生类中从何处开始

例如,对于记录A、B和C都有自己的数据成员,我们可以在两个不同的类别1中讨论这个问题。A、 B&C都有其虚拟功能;2.A、 B&C只有自己的数据成员,没有任何虚拟功能

A类{…};
B类{…};
C类:公共A、公共B{…};
C C;
B*B=&c

在C中,A应该放在B的顶部,那么指针B如何知道在C中从哪里开始寻址呢?

编译器知道布局,所以它将发出代码,这将计算
C
B
子对象的地址

让我们看一个简单的实际例子:

class A { int x; };
class B { int y; };
class C: public A, public B { };

B *get(C &c) {
    return &c;
}
get
中,编译器必须计算
B
C
中的位置。下面是编译代码()的示例:

这意味着编译器将向输入参数的地址(
c
)添加4个字节,并返回该字节(它添加4,因为
sizeof(A)
是4,编译器决定不添加任何额外的填充)


请注意,如果
A
为空,则
B
的地址可能与
C
相同。如果
A
不是空的(具有非静态数据成员,或具有虚拟函数),则
B
的地址可能会不同。但所有这些都是实现细节,取决于平台ABI(应用程序二进制接口)。

因为编译器知道A的大小。如果输出两个指针,您将看到指针的值已更改。试试看,地址不会改变。他们应该打印同样的东西。编辑:哦,如果他们有虚拟的方法,你是说?是的,那么它们就不同了。它不是。基类定义指定了它有哪些虚拟函数。当指向的对象是派生类的实例时,实现(aka编译器)确保所有虚拟函数调用都解析为最派生类的重写。实际上,实现通常使用虚拟函数表(vtables),这些表以某种形式包含指向所有虚拟函数的指针。当构造派生类的实例时,基类的vtable中会填充派生类的条目(因为“派生”部分的构造发生在“基类”部分之后)@TEDLYNMO至少一个
静态强制转换(&c)
静态强制转换(&c)
必须与
&c
不同,因为
A
B
子对象必须具有不同的地址。@如果它们具有虚拟方法,则为molbdnilo Yes。如果没有,它们都有相同的地址。最后一段是否受到某种影响?@Evg:是的,如果编译器将
A
放在第一位(并且
A
为空),那么EBO需要在相同的地址有
B
C
get(C&):                              # @get(C&)
        lea     rax, [rdi + 4]
        ret