有一个目标是谁的会员我需要找到的大小。 我特别询问对象的大小,而不是考虑v表。 此外,我不能修改它,所以我不能趁这个答案 。
有没有在C ++这个规定,超越总结硬编码sizeof
每个成员?
据我所知,V-表不是用C ++授权。 我也知道什么是我做这个信息将被广泛认为是“坏的形式”。 这个问题很简单询问,如果有可能,不认可的行为。
它已经到了我的注意,我需要澄清这个问题 。 我想了解这个问题是怎么投父到子。 也就是说,我希望保留孩子的v表,但复制母公司的成员变量: https://stackoverflow.com/a/31454039/2642059
接受的答案确实提供了我,我需要做到这一点的信息。 但是,在-尽管行为,我认为地方性的到最差的http://stackoverflow.com curiousguy 指出公认的答案的缺点 。
从接受的答案,多重继承的扩展显然是显而易见的,但它是有效的,答案应该包括它。 作为权宜之计我添加的如何处理多重继承一个活生生的例子: http://ideone.com/1QOrMz我会要求user2596732更新他的回答还是我会补充回答添加到如何处理的问题多重继承。
为了发现多态对象的布局,你可以比较指针成员对象; 简单的演示程序“绘制”的符号的对象的布局:
- 小写字母是数据成员的名称
- 大写字母是一个基类的名称
-
*
表示对象的一部分,该不属于任何构件子对象或基类子对象
存在用于每个字节一个符号(一个char
是由定义一个字节)。
vptr的(一个或多个)必须在“空”的空间,而不是分配给数据成员的空间。
类型定义如下:
struct T {
virtual void foo();
int i;
};
struct U {
virtual void bar();
long long l;
};
struct Der : T, U {
};
struct Der2 : virtual T, U {
};
struct Der3 : virtual T, virtual U {
};
输出是:
sizeof void* is 4
sizeof T is 8
sizeof i is 4
i is at offset 4
layout of T is
****iiii
sizeof U is 12
sizeof U::l is 8
l is at offset 4
layout of U is
****llllllll
sizeof Der is 20
Der::i is at offset 4
Der::l is at offset 12
Der::T is at offset 0
Der::U is at offset 8
layout of Der is
TTTTiiiiUUUUllllllll
sizeof Der2 is 20
Der2::i is at offset 16
Der2::l is at offset 4
Der2::T is at offset 12
Der2::U is at offset 0
layout of Der2 is
UUUUllllllllTTTTiiii
sizeof Der3 is 24
Der3::i is at offset 8
Der3::l is at offset 16
Der3::T is at offset 4
Der3::U is at offset 12
layout of Der3 is
****TTTTiiiiUUUUllllllll
见https://ideone.com/g5SZwk
因为我们知道,编译器使用vptrs,该vptrs的位置是在这些“图”明显。
关于用C ++继承
非虚继承
当不使用虚拟继承,基类的子对象继承图总是植根于最派生类树,即使当子类型图是不是树:
struct Repeated {
virtual void f();
virtual void g();
};
struct Left : Repeated {
void g();
};
struct Right : Repeated {
void g();
};
struct Bottom : Left, Right {
void f();
};
子类型图为:
Left
/ \
Repeated Bottom
\ /
Right
子对象图是:
Left::Repeated --- Left
\
Bottom
/
Right::Repeated --- Right
这是非虚拟继承的决定性影响。图表并不总是一致。 如果你不明白,你不明白非虚继承!
这意味着从转换Bottom*
到Repeated*
不明确。
在这个例子:
-
Bottom::f()
重载了Left::Repeated::f()
和Right::Repeated::f()
在同一时间。 -
Left::Repeated::g()
由重写Left::g()
-
Right::Repeated::g()
被重写Right::g()
这里的名称查找g
在Bottom
会失败的不确定性,所以它是使用不合格的错误g
的Bottom
。
虚拟继承
当使用虚拟继承,基类的子对象继承是最派生类作为唯一的终端的无环向图:
struct Unique { virtual void f(); };
struct Left : virtual Unique { void f(); };
struct Right : virtual Unique { void f(); };
struct Bottom : Left, Right { void f(); };
这里所有其他f()
声明重写Unique::f()
这里的子对象图相匹配的亚型图:
Left
/ \
Unique Bottom
\ /
Right
的sizeof(类)只包括一个虚函数表指针。
class A
{
public:
int a = 2;
int b = 2;
virtual void x() {
};
virtual void y() {
};
};
class B : public A
{
public:
int c = 2;
int d = 2;
virtual void y() {
};
};
class C : public A
{
public:
int c = 2;
int d = 2;
int e = 2;
virtual void x() {
};
};
所以,在这个例子中,
cout << sizeof(A)-sizeof(void*) << endl;
cout << sizeof(B)-sizeof(void*) << endl;
cout << sizeof(C)-sizeof(void*) << endl;
应该给你正确的答案。 8 16 20