获取对象的成员的sizeof [英] Get the sizeof Object's Members
问题描述
有一个对象谁是成员我需要找到的大小。我特别要求的对象的大小没有它的v表考虑。此外,我无法修改它,因此我无法利用此答案。
除了为每个成员加上硬编码的 sizeof
,在C ++中是否有这样的规定?
我知道v表不是由C ++强制。我也知道,我对这些信息做的任何事情都会被广泛认为是坏的形式。
这让我注意到了我需要澄清此问题。我想用这个问题学习的是如何把一个父母给孩子。也就是说,我想保留子级的v表,但复制父级的成员变量: http://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在偏移4
T的布局是
*** * iiii
sizeof U是12
sizeof U :: l是8
l是在偏移4
U的布局是
**** llllllll
sizeof Der is 20
Der :: i在偏移量4
Der :: l在偏移量12
Der :: T在偏移量0
Der :: U在偏移8
Der的布局是
TTTTiiiiUUUUllllllll
sizeof Der2是20
Der2 :: i在偏移16
Der2 :: l在偏移4
Der2 :: T在偏移量12
Der2 :: U位于偏移量0
Der2的布局是
UUUUllllllllTTTTiiii
Der3的sizeof是24
Der3 :: i位于偏移量8
Der3 :: l位于偏移量16
Der3 :: T位于偏移量4
Der3 :: U位于偏移量12
Der3的布局为
**** TTTTiiiiUUUUllllllll
因为我们知道编译器使用vptrs,vptrs的位置
关于C ++中的继承
非虚拟继承
当不使用虚拟继承时,即使当子类型图不是树时,基类subobjects继承图总是一个以最大派生类为根的树:
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 --- Left
\
Bottom
/
Right :: Repeated --- Right
这是非虚拟继承的关键效果:图形并不总是匹配。如果你不明白你不明白非虚拟继承!
这意味着从 Bottom *
到重复的*
是不明确的。
在此示例中:
-
Bottom :: f()
覆盖Left :: Repeated :: f code>和
Right :: Repeated :: f()
。 -
Left :: Repeated :: g()
被Left :: g()覆盖
- code> Right :: Repeated :: g()被覆盖
Right :: g()
此处查找 Bottom
g >会失败并带有歧义,因此在 Bottom
中使用不合格 g
>
虚继承
当使用虚拟继承时,基类subobjects继承是一个非循环有向图,作为唯一终端:
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()
。
这里子对象图匹配子类型图:
左
/ \
唯一底
\ /
右
There is an object who's members I need to find the size of. I am specifically asking for the object's size without it's v-table considered. Also, I cannot modify it, so I cannot take advantage of this answer.
Is there a provision for this in C++, beyond summing a hard-coded sizeof
for each member?
I am aware that v-tables are not mandated by C++. I am also aware that anything I do with this information will be widely considered "bad form". This question is simply asking if it's possible, not endorsing the behavior.
It has come to my attention that I need to clarify this question. 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://stackoverflow.com/a/31454039/2642059
The accepted answer does provide me the information I needed to do this. But, in-spite of behavior that I consider endemic to the worst of http://stackoverflow.com curiousguy points out a shortcoming of the accepted answer.
The extension from the accepted answer to multiple inheritance is patently obvious, but it is valid that the answer should include it. As a stopgap I've added a live example of how to deal with multiple inheritance: http://ideone.com/1QOrMz I will request that user2596732 updates his answer or I will add a supplementary answer to the question on how to deal with multiple inheritance.
In order to discover the layout of a polymorphic object, you can compare pointers to member objects; the simple demonstration program "draws" the layout of an object with symbols:
- a lowercase letter is the name of a data member
- an uppercase letter is the name of a base class
*
indicates part of the object that do not belong to any member subobject or base class subobject
There is a symbol for each byte (a char
is a byte by definition).
The vptr(s) must be in the "empty" space, the space not allocated for data members.
Type definitions are:
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 {
};
Output is:
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
Because we know the compiler is using vptrs, the locations of the vptrs are obvious in these "drawings".
About inheritance in C++
Non-virtual inheritance
When virtual inheritance is not used, the base class subobjects inheritance graph is always a tree rooted in the most derived class, even when the subtyping graph is not a tree:
struct Repeated {
virtual void f();
virtual void g();
};
struct Left : Repeated {
void g();
};
struct Right : Repeated {
void g();
};
struct Bottom : Left, Right {
void f();
};
The subtyping graph is:
Left
/ \
Repeated Bottom
\ /
Right
The subobject graph is:
Left::Repeated --- Left
\
Bottom
/
Right::Repeated --- Right
This is crucial effect of non-virtual inheritance: the graphs don't always match. If you don't understand that you don't understand non-virtual inheritance!
This implies that conversions from Bottom*
to Repeated*
are ambiguous.
In this example:
Bottom::f()
overrides bothLeft::Repeated::f()
andRight::Repeated::f()
at the same time.Left::Repeated::g()
is overridden byLeft::g()
Right::Repeated::g()
is overridden byRight::g()
Here the lookup of the name g
in Bottom
would fail with an ambiguity, so it would be an error to use an unqualified g
in Bottom
.
Virtual inheritance
When virtual inheritance is used, the base class subobjects inheritance is an acyclic directed graph with the most derived class as a unique terminal:
struct Unique { virtual void f(); };
struct Left : virtual Unique { void f(); };
struct Right : virtual Unique { void f(); };
struct Bottom : Left, Right { void f(); };
Here all other f()
declarations override Unique::f()
.
Here the subobject graph matches the subtype graph:
Left
/ \
Unique Bottom
\ /
Right
这篇关于获取对象的成员的sizeof的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!