- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在阅读 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/
目录 进程 其他相关概念 创建线程的两种方式 为什么使用start()方法而不直接使用run()方法 start()方法底层
CURL状态码列表 状态码 状态原因 解释 0 正常访问
ODBC连接类函数 odbc_connect函数:打开一个ODBC连接 odbc_close函数:关闭一个已经打开的ODBC连接 odbc_close_all函数:关闭所有已经打开的ODBC连
作为标题,如何计算从纪元1900到现在使用boost的持续时间? 编辑:很抱歉以前的问题太短。我将再次描述我的问题。 我有关于将生日另存为整数的问题。我创建了四个函数,用法如下: ptime转换为整数
前言 在Java中,有一个常被忽略 但 非常重要的关键字Synchronized今天,我将详细讲解 Java关键字Synchronized的所有知识,希望你们会喜欢 目录 1. 定义 J
详细 JVM 垃圾收集日志的时间戳是收集的开始还是结束? 2016-08-09T21:04:19.756-0400: 224890.317: [GC Desired survivor size 167
我在“Master-Detail”概念上苦苦挣扎,除了一点点(但很重要)的细微差别外,几乎所有东西都按预期工作。我应该在 Storyboard上更改什么以在详细信息 View (屏幕截图底部的右上角)
我希望能够显示表格的详细 View ,但不推送新屏幕,而只显示表格所在的详细 View 。 设置它的最佳方式是什么......如果真的可行的话? ---------------------------
我在我的博客中为我的帖子使用了详细 View ,每篇帖子都有评论,所以我想对它们进行分页,但我不知道该怎么做,因为我请求了帖子模型。我知道如何在功能 View 中执行此操作,但不知道如何在详细 Vie
在下面的代码中,与 pm 对齐,该行是否会 move 整个内存并将其分配给 pm,或者它只会 move p 指向的内存而不是整个数组? int main() { int*
1·下载 https://dev.mysql.com/downloads/mysql/ 2·安装服务 1)管理员运行cmd 2)D: 3)cd D:\mysql
今天以前一直用的SQL Server 2005做开发,偶尔也用MySQL,现入手公司项目,用到SQL Server 2008,于是乎必须安装它,免得出现其他很纠结的小问题,现将自己安装图解分享如下:
1. crontab命令选项 复制代码 代码如下: #crontab -u <-l, -r, -e> -u指定一个用
我们有一个 WPF 应用程序,它有一个主窗口/详细信息窗口,两者都是 WPF 数据网格。当您在上部数据网格中选择一行时,详细信息将显示在下部数据网格中。我想知道从 UI 的角度来看是否有任何关于如何处
在可视化 Perforce 客户端 (p4v) 中有一个选项: 显示文件操作的 p4 命令输出 启用后,在日志 Pane 中,我可以看到这样的详细日志记录: p4 sync /Users/az/ftp
在其他服务器上设置测试环境后,在几个API调用中出现错误。 99%肯定这是MySQL的事情,但是返回的错误根本没有帮助: global name 'sys' is not defined" 我已经导入
我正在维护一个通用的 iOS 应用程序,其开发已开始于 iOS 6。我正在为 iOS 7 更新 UI。现在我遇到了应用程序的 iPad 部分的奇怪问题。这部分遵循使用 UISplitViewContr
我希望我能正确描述这种情况。当它发生时很容易在屏幕上看到,但很难用语言解释,但我会尽力而为。 我有一个带有固定主视图 (UITableView) 和两个详细 View 之一的 UISplitViewC
我尝试在 eclipse 和 intelliJ 参数中使用垃圾收集记录器来配置简单的测试程序。尝试了不同类型的配置,但尚未创建日志文件。 -XX:+PrintGCDetails -XX:+PrintG
正如您所知,.cap 文件中的 java 小程序的输出文件格式必须通过智能卡读卡器/写卡器(如 ACR122 或任何其他读卡器)部署到 java 卡,而且我相信 java 卡与 java 卡之间的部署
我是一名优秀的程序员,十分优秀!