- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
这与之前的许多问题类似,但它提出了一些我无法找到答案的问题。
#include <iostream>
using namespace std;
class Base1 {
public:
int b1_data;
virtual void b1_fn() {cout << "I am b1\n";}
};
class Base2 {
public:
int b2_data;
virtual void b2_fn() {cout << "I am b2\n";}
};
class Derived : public Base1, public Base2 {
public:
int d_data;
void b1_fn() {cout << "I am b1 of d\n";}
void b2_fn() {cout << "I am b2 of d\n";}
};
int main() {
Derived *d = new Derived();
Base1 *b1 = d;
/*My observation mentioned below is implementation dependant, for learning,
I assume, there is vtable for each class containing virtual function and in
case of multiple inheritance, there are multiple vtables based on number of
base classes(hence that many vptr in derived object mem layout)*/
b1->b1_fn(); // invokes b1_fn of Derived because d points to
// start of d's memory layout and hence finds vtpr to
// Derived vtable for Base1(this is understood)
Base2 *b2 = d;
b2->b2_fn(); // invokes b2_fn of Derived but how? I know that it "somehow"
// gets the offset added to d to point to corresponding Base2
// type layout(which has vptr pointing to Derived vtable for
// Base2) present in d's memory layout.
return 0;
}
具体来说,b2如何指向Derived for Base2的vtable的vptr到b2_fn()?我试过从 gcc 中查看 memlayout 转储但无法弄清楚。
最佳答案
编译器在多重继承的情况下,构建他的 vtables 以便每个子对象都有一个合适的 vtable。当然,这是依赖于实现的(就像 vtables 本身),但它会像这样组织:
Base1
对象有一个指向 vtable 的 vptr,该 vtable 包含指向 Base1::b1_fn
的唯一指针>Base2
对象有一个指向 vtable 的 vptr,该 vtable 包含指向 Base2::b2_fn
的唯一指针>Derived
对象有一个指向 vtable 的 vptr,该 vtable 以对应于 Base1
的 vtable layout 开头,但使用 Base2
的 vtable 的缺失元素对其进行了扩展。对于“布局”,我的意思是 b1_fn()
的指针处于相同的偏移量,但它可能指向一个覆盖函数。因此,此处的表将包含 Derived::b1_fn
,后跟 Derived::b2_fn
。这种组合布局确保 Derived
中的 Base1
子对象可以与其子对象共享 vtable。 Derived
对象由 2 个子对象组成:所以 Base1
子对象后面会跟着一个 Base2
子对象,它有它自己的 vtable,使用 Base2
所需的布局,但同样使用 Base2::b2_fn
而不是原始布局。 当将 Derived
指针转换为 Base2
指针时,编译器将使它指向 Base2
子对象及其 vtable,通过应用在编译时确定的固定偏移量。
顺便说一句,如果您要进行向下转换,编译器会类似地使用另一个方向的固定偏移量,以找到 Derived
的开始。这一切都非常简单,直到您使用虚拟基地,其中固定偏移技术不再起作用。然后必须按照此 other SO answer 中的说明使用虚拟基指针
这Dr.Dobb's article是对所有这些布局的最好解释和一些好的图片。
关于c++ - 在多重继承的情况下选择 vptr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36091456/
我是 Java 新手,这是我的代码, if( a.name == b.name && a.displayname == b.displayname && a.linknam
在下面的场景中,我有一个 bool 值。根据结果,我调用完全相同的函数,唯一的区别是参数的数量。 var myBoolean = ... if (myBoolean) { retrieve
我是一名研究 C++ 的 C 开发人员: 我是否正确理解如果我抛出异常然后堆栈将展开直到找到第一个异常处理程序?是否可以在不展开的情况下在任何 throw 上打开调试器(即不离开声明它的范围或任何更高
在修复庞大代码库中的错误时,我观察到一个奇怪的情况,其中引用的动态类型从原始 Derived 类型更改为 Base 类型!我提供了最少的代码来解释问题: struct Base { // some
我正在尝试用 C# 扩展给定的代码,但由于缺乏编程经验,我有点陷入困境。 使用 Visual Studio 社区,我尝试通过控制台读出 CPU 核心温度。该代码使用开关/外壳来查找传感器的特定名称(即
这可能是一个哲学问题。 假设您正在向页面发出 AJAX 请求(这是使用 Prototype): new Ajax.Request('target.asp', { method:"post", pa
我有以下 HTML 代码,我无法在所有浏览器中正常工作: 我试图在移动到
我对 Swift 很陌生。我如何从 addPin 函数中检索注释并能够在我的 addLocation 操作 (buttonPressed) 中使用它。我正在尝试使用压力触摸在 map 上添加图钉,在两
我设置了一个详细 View ,我是否有几个 Nib 文件根据在 Root View Controller 的表中选择的项目来加载。 我发现,对于 Nibs 的类,永远不会调用 viewDidUnloa
我需要动态访问 json 文件并使用以下代码。在本例中,“bpicsel”和“temp”是变量。最终结果类似于“data[0].extit1” var title="data["+bpicsel+"]
我需要使用第三方 WCF 服务。我已经在我的证书存储中配置了所需的证书,但是在调用 WCF 服务时出现以下异常。 向 https://XXXX.com/AHSharedServices/Custome
在几个 SO 答案(1、2)中,建议如果存在冲突则不应触发 INSERT 触发器,ON CONFLICT DO NOTHING 在触发语句中。也许我理解错了,但在我的实验中似乎并非如此。 这是我的 S
如果进行修改,则会给出org.hibernate.NonUniqueObjectException。在我的 BidderBO 类(class)中 @Override @Transactional(pr
我使用 indexOf() 方法来精细地查找数组中的对象。 直到此刻我查了一些资料,发现代码应该无法正常工作。 我在reducer中尝试了上面的代码,它成功了 let tmp = state.find
假设我有以下表格: CREATE TABLE Game ( GameID INT UNSIGNED NOT NULL, GameType TINYINT UNSIGNED NOT NU
代码: Alamofire.request(URL(string: imageUrl)!).downloadProgress(closure: { (progress) in
我是一名优秀的程序员,十分优秀!