c++ - 编译器关于 this 指针和虚函数的详细信息

标签 c++ pointers virtual-functions vtable this-pointer

我正在阅读 Bjarne 的论文:“Multiple Inheritance for C++”。

在第 3 节,第 370 页,Bjarne 说“编译器将成员函数的调用转换为带有“额外”参数的“普通”函数调用;“额外”参数是指向对象的指针成员函数被调用。”

考虑一个简单的类 A:

class A {
    int a;
    void f(int i);
};

成员函数A::f的调用:

A* pa;
pa->f(2)

被编译器转化为“普通函数调用”:

f__F1A(pa, 2)

pa 作为 this 指针传递。上面的例子很容易理解。

考虑以下代码片段:

class A {int a; void f(int);};
class B : A {int b; void g(int);};
class C : B {int c; void h(int);};

问题 1:

成员函数A::f的调用:

C* pc = new C;
pc->g(int)

被编译器转化为“普通函数调用”:

g__G1C(pc, int) or g__G1B((*B)pc, int)

this 指针是*pc 还是(*B)pc? 另一个问题是编译器如何知道成员函数在哪里?

让我们通过添加 virtual 关键字使上面的示例更有趣。

class A {
    int a;
    virtual void f(int);
    virtual void g(int);
    virtual void h(int);
};
class B : A {int b; void g(int); };
class C : B {int c; void h(int); };

C 类对象 C 看起来像:

C:

-----------                vtbl:
+0:  vptr -------------->  -----------
+4:  a                     +0: A::f
+8:  b                     +4: B::g
+12: c                     +8: C::h
-----------                -----------  

编译器将对虚函数的调用转换为间接调用。例如,

C* pc;
pc->g(2)

变成这样:

(*((*pc)[1]))(pc, 2)

Bjarne 的论文告诉了我以上结论。

问题 2:

(1) 在 vtbl 中,我相信这些函数指针是在 运行时。编译器如何知道第二个函数指针 应该指向 B 类对 g 的实现吗?怎么样 编译数字呢?

(2) 在上面的例子中,所有成员都是 int 并且我们假设 编译器为 int 分配 4 字节内存。如果成员(member)是 char,编译器是否仍然为char分配4字节内存?还是只有一个字节?

(3) (*((*pc)[1]))(pc, 2),这里的this指针是pc,为什么不呢 (*B)个人计算机? this指针的传递有什么规律吗?

谁能帮我回答这些问题?对此,我真的非常感激。我有一个 明天的截止日期确实与这些问题有关。请帮忙!!!

最佳答案

Question 1:

A call of the member function A::f:

C* pc = new C;
pc->g(int)

这不是对 A::f() 的调用。这是对 B::g() 的调用。

is transformed by the compiler to an "ordinary function call":

g__G1C(pc, int) or g__G1B((*B)pc, int)

Is the this pointer a *pc or (*B)pc?

都没有。这是一个 B*

Another question is how the compile knows where the member functions are?

事实并非如此。它知道他们的名字。链接器分配它们的地址。

Question 2:

(1) How does the compiler know the second function pointer should point to the class B's implementation of the g? How the compiler figures it?

因为是C的vtbl,而且C继承自B,而B对g()的定义最近。

(2) In the above example, all members are int and we assume that the compiler assigns 4 bytes memory for the int. What if the member is char, does the compiler still assigns 4 bytes memory for the char? Or just one byte?

这取决于处理器、编译器、编译器选项、周围#pragmas 等的对齐和打包规则。

(3) (*((*pc)[1]))(pc, 2), the this pointer here is a pc, why not (*B)pc?

这个假设与 your other question 相矛盾.它是 B*

Is there any rule for the passing this pointer?

见上文。

关于c++ - 编译器关于 this 指针和虚函数的详细信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30746461/

相关文章:

c++ - 指向前一个值而不递减指针

c - 在C中打印数组名称的地址

c++ - 集合适配器 - 省略依赖底层集合的 T

c++ - 非指针类成员 : how good is it?

c++ - 什么时候浮点变量不等于自身

c++ - 如何使用指针用随机数填充二维数组

c++ - 通过指针访问私有(private)虚拟成员函数

c++ - 体系结构 x86_64 的 undefined symbol ,共享 Util 库,使用 cmake 构建,

c++ - 从 OBB 的模型矩阵中提取 3x3 旋转矩阵

c# - 像 C# 一样模仿 Python(纯)虚函数