我的程序中出现了一个非常令人困惑的错误。我想我可能有两个同一类的不同对象,我认为我有相同的对象。这很令人困惑,因为我正在处理一个非常大的框架,在这个框架中获取指向我需要的对象的指针并不简单。
我的问题是,如果我有一个继承自Base的类Derived,并且我有一个指向Derived对象的指针,我如何从派生对象中获取Base对象的地址?我正在使用基类的源代码,并在Base中打印出“this”的地址。在我的代码的另一部分中,检索指向Derived的指针。我需要能够通过Derived对象打印Base对象的地址,以确定我是否有指向我需要的特定Derived对象的指针。
我可能对地址如何在继承中使用C ++有很大的误解。也许它们只是一个对象,而不是链接到派生对象的基础对象?
非常感谢
编辑: 我想这样做的原因纯粹是为了调试。问题是我使用的代码库不包含很多接口或受保护的成员,所以我不得不编辑源代码来访问某些信息。但是,当我调用我使用特定的Derived指针添加到Base类的方法时,我的程序崩溃了。我需要能够在这种情况下打印基础对象的地址,以便我可以确定这是否是正确的对象或我是否收到此错误,因为我实际上有一个指向错误对象的指针。我意识到我可以将代码添加到派生类中以使其打印其地址,但我只是想知道是否有可能在不编辑源代码的情况下获取地址。感谢
答案 0 :(得分:5)
从指向派生类的指针变为指向基类的指针很简单:
Derived * derived_ptr = < some pointer >;
Base * base_ptr = derived_ptr;
如果您想要迂腐,可以在作业的右侧使用static_cast
:
Base * base_ptr = static_cast<Base*>(derived_ptr);
从指向基类的指针到指向派生类的指针使用dynamic_cast
:
Derived * derived_ptr = dynamic_cast<Derived*>(base_ptr);
但是,这并不总是有效。您需要启用运行时类型ID,并且基类需要至少有一个虚拟方法。
在你这样做之前,你为什么需要从基指针转到派生指针?这是一条线索,您可能需要重新考虑您的设计。
答案 1 :(得分:2)
只有一个对象,它由Base和Derived组成 - 也就是说,在大多数实现中,Base被放在Derived旁边的内存中。这意味着Base *与一般情况下的Derived *不同,但它们会非常接近。
现在,您可以从Derived *中轻松获取Base *,演员是隐式的,但您也可以将其显式化:
Derived* dptr = ...;
Base* ptr = dptr;
但是,没有什么能阻止单个派生对象包含多个 Base
对象。通常情况并非如此,但可能会发生。这意味着你无法比较Base
指针,并希望知道你是在处理同一个对象,只是同一个Base
子对象。
答案 2 :(得分:1)
在单继承的简单情况下,对于大多数编译器:
如果你有一个指向派生类的指针,那么它与指向基类的指针相同。两个指针都具有相同的值并指向相同的内存地址。
在内存中,如果创建派生类的实例,它将被布局为基础对象的成员,后跟派生对象的成员。基类成员构成派生对象的一部分。
class Base
{
int b;
};
class Derived : public Base
{
int d;
};
在内存中,说Derived指针是0400.然后:
0400 byte 1 of b
0401 byte 2 of b
0402 byte 3 of b
0403 byte 4 of b
0404 byte 1 of d
0405 byte 2 of d
0406 byte 3 of d
0407 byte 4 of d
派生对象由基本成员和派生自己的成员组成,两者的地址从0400开始。
就是这样,在0400,派生的基础对象部分被定位。因此,base和derived具有相同的地址。