获取对象成员的大小
Get the sizeof Object's Members
有一个对象的成员,我需要找到它的大小。我特别要求对象的大小 without 它是 v-table 考虑的。另外,我不能修改它,所以我不能利用 .
除了对每个成员硬编码 sizeof
求和之外,在 C++ 中是否有这方面的规定?
我知道 v-tables 不是 C++ 强制要求的。我也知道我对这些信息所做的任何事情都会被广泛考虑 "bad form"。这个问题只是在询问是否可能,而不是认可这种行为。
它引起了我的注意. What I wanted to learn with this question was how to cast a parent to a child. That is, I wanted to preserve the child's v-table, but copy the parent's member variables:
已接受的答案确实为我提供了执行此操作所需的信息。但是,尽管我认为 http://whosebug.com curiousguy .
最糟糕的行为是地方病
从已接受的答案到多重继承的扩展显然是显而易见的,但答案应该包含它是有效的。作为权宜之计,我添加了一个如何处理多重继承的实例:http://ideone.com/1QOrMz I will request that user2596732 更新他的答案,或者我将添加一个关于如何处理多重继承的问题的补充答案。
没有。
sizeof(Class) 只包含一个 VTable 指针。
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
为了发现多态对象的布局,你可以比较指向成员对象的指针;简单的演示程序 "draws" 带有符号的对象的布局:
- 小写字母是数据成员的名字
- 大写字母是碱基的名称class
*
表示对象的一部分不属于任何成员子对象或基class子对象
每个字节都有一个符号(根据定义,char
是一个字节)。
vptr(s) 必须在 "empty" space 中,space 未分配给数据成员。
类型定义为:
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
因为我们知道编译器正在使用 vptrs,所以 vptrs 的位置在这些 "drawings".
中很明显
关于 C++ 中的继承
非虚继承
当不使用虚拟继承时,基础 class 子对象继承图始终是一棵以最派生的 class 为根的树,即使子类型化图不是树也是如此:
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()
覆盖
此处在 Bottom
中查找名称 g
会因歧义而失败,因此在 Bottom
中使用不合格的 g
将是错误的。
虚拟继承
当使用虚拟继承时,基础class子对象继承是以最派生class为唯一终端的无环有向图:
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
有一个对象的成员,我需要找到它的大小。我特别要求对象的大小 without 它是 v-table 考虑的。另外,我不能修改它,所以我不能利用
除了对每个成员硬编码 sizeof
求和之外,在 C++ 中是否有这方面的规定?
我知道 v-tables 不是 C++ 强制要求的。我也知道我对这些信息所做的任何事情都会被广泛考虑 "bad form"。这个问题只是在询问是否可能,而不是认可这种行为。
它引起了我的注意
已接受的答案确实为我提供了执行此操作所需的信息。但是,尽管我认为 http://whosebug.com curiousguy
从已接受的答案到多重继承的扩展显然是显而易见的,但答案应该包含它是有效的。作为权宜之计,我添加了一个如何处理多重继承的实例:http://ideone.com/1QOrMz I will request that user2596732 更新他的答案,或者我将添加一个关于如何处理多重继承的问题的补充答案。
没有。
sizeof(Class) 只包含一个 VTable 指针。
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
为了发现多态对象的布局,你可以比较指向成员对象的指针;简单的演示程序 "draws" 带有符号的对象的布局:
- 小写字母是数据成员的名字
- 大写字母是碱基的名称class
*
表示对象的一部分不属于任何成员子对象或基class子对象
每个字节都有一个符号(根据定义,char
是一个字节)。
vptr(s) 必须在 "empty" space 中,space 未分配给数据成员。
类型定义为:
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
因为我们知道编译器正在使用 vptrs,所以 vptrs 的位置在这些 "drawings".
中很明显关于 C++ 中的继承
非虚继承
当不使用虚拟继承时,基础 class 子对象继承图始终是一棵以最派生的 class 为根的树,即使子类型化图不是树也是如此:
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()
覆盖
此处在 Bottom
中查找名称 g
会因歧义而失败,因此在 Bottom
中使用不合格的 g
将是错误的。
虚拟继承
当使用虚拟继承时,基础class子对象继承是以最派生class为唯一终端的无环有向图:
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