- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我对 virtual 的对象大小有一些疑问。
1)虚函数
class A {
public:
int a;
virtual void v();
}
A类的大小是8字节....一个整数(4字节)加一个虚拟指针(4字节)很清楚!
class B: public A{
public:
int b;
virtual void w();
}
B 类的大小是多少?我使用 sizeof B 进行了测试,它打印出来12
是不是说B类和A类都有虚函数也只有一个vptr?为什么只有一个vptr?
class A {
public:
int a;
virtual void v();
};
class B {
public:
int b;
virtual void w();
};
class C : public A, public B {
public:
int c;
virtual void x();
};
C的sizeof是20.......
似乎在这种情况下,布局中有两个 vptrs.....这是怎么发生的?我认为两个 vptr 一个用于 A 类,另一个用于 B 类....所以没有用于 C 类虚函数的 vptr?
我的问题是,继承的vptr数量有什么规定?
2)虚拟继承
class A {
public:
int a;
virtual void v();
};
class B: virtual public A{ //virtual inheritance
public:
int b;
virtual void w();
};
class C : public A { //non-virtual inheritance
public:
int c;
virtual void x();
};
class D: public B, public C {
public:
int d;
virtual void y();
};
A 的大小是 8 个字节 -------------- 4(int a) + 4 (vptr) = 8
B的sizeof是16字节 -------------- 没有virtual应该是4 + 4 + 4 = 12。为什么这里还有4个字节? B类布局是怎样的?
C 的大小为 12 个字节。 -------------- 4 + 4 + 4 = 12。很明显!
D 的 sizeof 是 32 字节 -------------- 应该是 16(class B) + 12(class C) + 4(int d) = 32,对吗?
class A {
public:
int a;
virtual void v();
};
class B: virtual public A{ //virtual inheritance here
public:
int b;
virtual void w();
};
class C : virtual public A { //virtual inheritance here
public:
int c;
virtual void x();
};
class D: public B, public C {
public:
int d;
virtual void y();
};
A 的大小为 8
B 的大小为 16
C 的大小为 16
sizeof D 是 28 是否意味着 28 = 16(class B) + 16(class C) - 8(class A) + 4(这是什么?)
我的问题是,为什么在应用虚拟继承时会有额外的空间?
在这种情况下,对象大小的基本规则是什么?
virtual应用于所有基类和部分基类有什么区别?
最佳答案
这是所有实现定义的。我正在使用 VC10 Beta2。帮助理解这些东西的关键(虚函数的实现),你需要知道 Visual Studio 编译器中的一个 secret 开关,/d1reportSingleClassLayoutXXX。我会在一秒钟内解决这个问题。
基本规则是,对于任何指向对象的指针,vtable 都需要位于偏移量 0 处。这意味着多个 vtable 用于多重继承。
这里有几个问题,我将从头开始:
Does it mean that only one vptr is there even both of class B and class A have virtual function? Why there is only one vptr?
这就是虚函数的工作方式,你希望基类和派生类共享同一个虚表指针(指向派生类中的实现。
It seems that in this case, two vptrs are in the layout.....How does this happen? I think the two vptrs one is for class A and another is for class B....so there is no vptr for the virtual function of class C?
这是 C 类的布局,由/d1reportSingleClassLayoutC 报告:
class C size(20):
+---
| +--- (base class A)
0 | | {vfptr}
4 | | a
| +---
| +--- (base class B)
8 | | {vfptr}
12 | | b
| +---
16 | c
+---
你是对的,有两个虚表,每个基类一个。这就是它在多重继承中的工作方式;如果将 C* 转换为 B*,指针值将调整 8 个字节。 vtable 仍然需要位于偏移量 0 处,虚函数调用才能正常工作。
A 类的上述布局中的 vtable 被视为 C 类的 vtable(当通过 C* 调用时)。
The sizeof B is 16 bytes -------------- Without virtual it should be 4 + 4 + 4 = 12. why there is another 4 bytes here? What's the layout of class B ?
这是本例中 B 类的布局:
class B size(20):
+---
0 | {vfptr}
4 | {vbptr}
8 | b
+---
+--- (virtual base A)
12 | {vfptr}
16 | a
+---
如您所见,有一个额外的指针来处理虚拟继承。虚拟继承很复杂。
The sizeof D is 32 bytes -------------- it should be 16(class B) + 12(class C) + 4(int d) = 32. Is that right?
不,36 字节。同样处理虚拟继承。本例中 D 的布局:
class D size(36):
+---
| +--- (base class B)
0 | | {vfptr}
4 | | {vbptr}
8 | | b
| +---
| +--- (base class C)
| | +--- (base class A)
12 | | | {vfptr}
16 | | | a
| | +---
20 | | c
| +---
24 | d
+---
+--- (virtual base A)
28 | {vfptr}
32 | a
+---
My question is , why there is an extra space when virtual inheritance is applied?
虚基类指针,比较复杂。基类在虚拟继承中被“组合”。不是将基类嵌入到类中,而是该类将在布局中具有指向基类对象的指针。如果您有两个使用虚拟继承的基类(“菱形”类层次结构),它们将都指向对象中的同一个虚拟基类,而不是拥有该基类的单独拷贝。
What's the underneath rule for the object size in this case?
要点;没有规则:编译器可以做任何它需要做的事情。
最后一个细节;制作我正在编译的所有这些类布局图:
cl test.cpp /d1reportSingleClassLayoutXXX
其中 XXX 是您要查看其布局的结构/类的子字符串匹配项。使用这个你可以自己探索各种继承方案的影响,以及为什么/在哪里添加填充等。
关于具有虚拟方法的 C++ 对象大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37782571/
这是代码片段。 请说出这种用小内存存储大数据的算法是什么。 public static void main(String[] args) { long longValue = 21474836
所以我使用 imap 从 gmail 和 outlook 接收电子邮件。 Gmail 像这样编码 =?UTF-8?B?UmU6IM69zq3OvyDOtc68zrHOuc67IG5ldyBlbWFpb
很久以前就学会了 C 代码;想用 Scheme 尝试一些新的和不同的东西。我正在尝试制作一个接受两个参数并返回两者中较大者的过程,例如 (define (larger x y) (if (> x
Azure 恢复服务保管库有两个备份配置选项 - LRS 与 GRS 这是一个有关 Azure 恢复服务保管库的问题。 当其驻留区域发生故障时,如何处理启用异地冗余的恢复服务保管库?如果未为恢复服务启
说,我有以下实体: @Entity public class A { @Id @GeneratedValue private Long id; @Embedded private
我有下一个问题。 我有下一个标准: criteria.add(Restrictions.in("entity.otherEntity", getOtherEntitiesList())); 如果我的
如果这是任何类型的重复,我会提前申请,但我找不到任何可以解决我的具体问题的内容。 这是我的程序: import java.util.Random; public class CarnivalGame{
我目前正在使用golang创建一个聚合管道,在其中使用“$ or”运算符查询文档。 结果是一堆需要分组的未分组文档,这样我就可以进入下一阶段,找到两个数据集之间的交集。 然后将其用于在单独的集合中进行
是否可以在正则表达式中创建 OR 条件。 我正在尝试查找包含此类模式的文件名列表的匹配项 第一个案例 xxxxx-hello.file 或者案例二 xxxx-hello-unasigned.file
该程序只是在用户输入行数时创建菱形的形状,因此它有 6 个 for 循环; 3 个循环创建第一个三角形,3 个循环创建另一个三角形,通过这 2 个三角形和 6 个循环,我们得到了一个菱形,这是整个程序
我有一个像这样的查询字符串 www.google.com?Department=Education & Finance&Department=Health 我有这些 li 标签,它们的查询字符串是这样
我有一个带有静态构造函数的类,我用它来读取 app.config 值。如何使用不同的配置值对类进行单元测试。我正在考虑在不同的应用程序域中运行每个测试,这样我就可以为每个测试执行静态构造函数 - 但我
我正在寻找一个可以容纳多个键的容器,如果我为其中一个键值输入保留值(例如 0),它会被视为“或”搜索。 map, int > myContainer; myContainer.insert(make_
我正在为 Web 应用程序创建数据库,并正在寻找一些建议来对可能具有多种类型的单个实体进行建模,每种类型具有不同的属性。 作为示例,假设我想为“数据源”对象创建一个关系模型。所有数据源都会有一些共享属
(1) =>CREATE TABLE T1(id BIGSERIAL PRIMARY KEY, name TEXT); CREATE TABLE (2) =>INSERT INTO T1 (name)
我不确定在使用别名时如何解决不明确的列引用。 假设有两个表,a 和 b,它们都有一个 name 列。如果我加入这两个表并为结果添加别名,我不知道如何为这两个表引用 name 列。我已经尝试了一些变体,
我的查询是: select * from table where id IN (1,5,4,3,2) 我想要的与这个顺序完全相同,不是从1...5,而是从1,5,4,3,2。我怎样才能做到这一点? 最
我正在使用 C# 代码执行动态生成的 MySQL 查询。抛出异常: CREATE TABLE dump ("@employee_OID" VARCHAR(50)); "{"You have an er
我有日期 2016-03-30T23:59:59.000000+0000。我可以知道它的格式是什么吗?因为如果我使用 yyyy-MM-dd'T'HH:mm:ss.SSS,它会抛出异常 最佳答案 Sim
我有一个示例模式,它的 SQL Fiddle 如下: http://sqlfiddle.com/#!2/6816b/2 这个 fiddle 只是根据 where 子句中的条件查询示例数据库,如下所示:
我是一名优秀的程序员,十分优秀!