Ste*_*ler 8 c++ pointers casting
我发现了一些似乎与我的问题有关的其他问题,但没有一个直接回答它(即使是几乎同名的问题).
我有一个源自两个父母的C++子类.我创建了该类的一个对象,然后将它的引用转换为它的两个父类.转换值不相同,但仍然是子引用的值.这是代码:
class Mom
{
public:
int a = 1;
};
class Dad
{
public:
int b = 2;
};
class Child : public Mom, public Dad
{
public:
int c = 3;
};
int main()
{
Child* c = new Child; // 0x00C5A618
Mom* m = c; // 0x00C5A618
Dad* d = c; // 0x00C5A61C
return 0;
}
Run Code Online (Sandbox Code Playgroud)
现在,我猜测通过应用static_cast <>获得的地址是实际子对象的地址.碰巧,它Mom是第一个子对象,所以它实际上具有相同的地址Child.Dad是第二个子对象,因此它位于不同的地址.
据我所知,C风格的演员阵容就像这样
Mom* m = (Mom*)c;
Dad* d = (Dad*)c;
Run Code Online (Sandbox Code Playgroud)
如果这样做是合法的,将应用static_cast <>.实际上,当我实际编译并执行该版本时,我会看到与以前相同的行为.
继续这个闪烁的传奇,使用隐式演员,像这样
Mom* m = c;
Dad* d = c;
Run Code Online (Sandbox Code Playgroud)
也表现出相同的行为,我从中推断,当等效的显式转换是合法的时,隐式转换也会应用static_cast <>.
向下倾斜Child做同样的事情:
Child* k = static_cast<Child*>(d); // 0x00C5A618
Run Code Online (Sandbox Code Playgroud)
在该值k从值是不同的d,其在被设置回原来的值c.
我猜测,在这种情况下,有一个运行时检查,看是否确实,d指向Dad一个的子对象Child的对象.
到目前为止,这一切都是有道理的,但我很惊讶,对于单独派生的层次结构,没有这样的地址调整(如果这是正确的调用它).也就是说,如果我的层次结构只是Mom- > Dad- > ,则将Child对a的引用Child转换为指向a Mom或Dad从不更改值的指针:
class Mom
{
public:
int a = 1;
};
class Dad : public Mom
{
public:
int b = 2;
};
class Child : public Dad
{
public:
int c = 3;
};
int main()
{
Child* c = new Child; // 0x00C5A618
Mom* m = c; // 0x00C5A618
Dad* d = c; // 0x00C5A618
Child* k = static_cast<Child*>(d); // 0x00C5A618
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我希望它可以通过每个附加子类所需的存储大小或四个字节(int的大小)来改变.但是,他们没有.所有在上面的例子中的指针的,c,m,d,和k,具有相同的值.
所以,现在我猜测的对象是在内存布局与Mom以最低的地址对象时,额外需要的空间Dad来下一个对象,并额外需要的空间Child即将过去.由于a Dad是a Mom,Dad地址与地址相同Mom,不是吗?
同样,a Child也是a Mom,因此它的地址也与它自己的Mom子对象的地址相同.
所以...
我认为它的工作方式如下:在内存中,对象相互跟随,在纯粹单独派生的层次结构中,向上转换和向下转换始终产生相同的地址,而在多个派生的层次结构中,某些向上转换产生不同的地址,因为不是所有子对象将从派生对象的相同地址开始.像这样:
Possible Memory Layout for a Singly Derived Hierarchy
+-------+-----+-----+---+
| Child : Dad : Mom : a |
| | +-----+---+
| | : b |
| +-----------+---+
| : c |
+-----------------------+
Possible Memory Layout for a Multiply Derived Hierarchy
+-------+-----+---+
| Child : Mom : a |
| +-----+---+
| : Dad : b |
| +-----+---+
| : c |
+-----------------+
Run Code Online (Sandbox Code Playgroud)
对不起,我有点絮絮叨叨,但我的问题是这样的事实:对于一个乘法派生对象的某些基类的向上转换会改变引用的值,这是事后修改后的值是地址的结果内存中的基础对象?
是的你是对的。向上转换指针给出父子对象的地址,该地址存储在子类内部的某个位置。通常父子对象存储在子对象的开头,因此指向子对象和基子对象的指针是相同的。
在多重继承的情况下,所有父类不可能占用相同的内存(让我们忽略可能的空基优化),因此除一个之外的所有基类地址都必须与子类地址不同。