基类构造函数中指向派生类的指针

pointer to derived class in base class constructor

本文关键字:指针 派生 构造函数 基类      更新时间:2023-10-16

(注意,这是对我实际设计的过度简化)

class CParentA;
class C_Child
public:
    C_Child(C_ParentB* parent) : m_parent(parent){}; 
    virtual ~C_Child();
    CParentB*   m_parent;
};
class C_ParentA : public C_Child
{
public:
    C_ParentA(C_GrandParent *gp) : C_Child(gp){};
    virtual ~C_ParentA(){};
}
class C_ParentB
{
public:
    C_ParentB(){};
    virtual ~C_ParentB(){};
    void    foo(){};
}
class C_GrandParent : public C_ParentB, public C_ParentA
{
public:
    C_GrandParent() : C_ParentA(this){};
    virtual ~C_GrandParent();
}

main()
{
    C_GrandParent   gp;
    gp.m_parent->foo();
}

似乎parentB的指针,发送到子的构造函数,是无效的,但当祖父创建。我曾认为,即使父类没有完全构造,它的指针(this)仍然是有效的。我还尝试让ParentB是存储在grandparent中的指针,并在grandparent构造函数中动态创建对象。但这显然有相同的结果。

fww:这样做的目的是:grandparent有许多parents,其中一些与children一起。一个child可能需要访问另一个childparent (uncle/cousin)。我原以为把他们都置于一个族长之下就能处理好家庭成员之间的大部分关系。尽管如此,设置合适的指针似乎是个问题。

首先,不清楚你在问什么,所以我只是想推测一下。你提出了一个不可行的设计,所以你一定是在寻求替代方案,但你没有给出你正在尝试做什么的信息。

其次,当类A派生类B时,我们通常说B是基类或父类,A是派生类或子类。你用了相反的术语,这很令人困惑。

现在,我只假设C_Child中的CParentB* m_parent;应该引用相同的C_Child对象,视为CParentB。你不需要为此存储指针。给定一个C_Child& r引用或C_Child* p指针,您可以简单地分别说

dynamic_cast<CParentB&>(r)
dynamic_cast<CParentB*>(p)
如果r,p没有引用CParentB对象,

两者将以不同的方式失败。dynamic_cast允许您浏览整个类层次结构,并在运行时检查强制转换是否有效。如果类不是多态的,可以使用static_cast

在任何情况下,请记住,在完全构造派生类的任何对象之前,需要首先构造其基类。因此,在此之前,请避免以任何方式处理部分构造的对象,例如调用其方法,特别是虚拟方法。