传递(在构造函数中)指向包含一个糟糕设计的类的指针,如果是,那么解决方案是什么

NoS*_*tAl 5 c++ object-design

经常我会遇到类似的代码

/*initializer list of some class*/:m_member(some_param,/* --> */ *this)
Run Code Online (Sandbox Code Playgroud)

这样做的原因是m_member可以从包含它的类中调用成员函数... aka

//code in class that is m_member instance of

    m_parent->some_function();
Run Code Online (Sandbox Code Playgroud)

我个人不喜欢它,因为我认为它是可怜的设计("亲爱的孩子,你知道你在做什么对你的课程封装"),但我想知道一般这种行为不好,如果是这样,如何避免这种设计.

编辑:请不要把重点放在initalizer列表中,让我们说它是在ctor体内.

Who*_*aig 2

这可能是灾难性的,因为您的父级不是在参考集的时间构建的。以下示例将演示这一点:

#include <iostream>
using namespace std;

struct TheParent;

struct TheChild
{
    TheChild(TheParent& parent);
    TheParent& myParent;
};

struct TheParent
{
    TheParent()
      : mychild(*this)
      , value(1)
    {
        cout << "TheParent::TheParent() : " << value << endl;
    }

    TheChild mychild;
    int value;
};

TheChild::TheChild(TheParent& parent)
   : myParent(parent)
{
    cout << "TheChild::TheChild() : " << myParent.value << endl;
};

int main()
{
    TheParent parent;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

产生以下输出,清楚地注意到父对象的不确定状态:

TheChild::TheChild() : 1606422622
TheParent::TheParent() : 1
Run Code Online (Sandbox Code Playgroud)

底线:不要这样做。您最好使用动态分配,但即使这样也有警告:

#include <iostream>
using namespace std;

struct TheParent;

struct TheChild
{
    TheChild(TheParent& parent);
    TheParent& myParent;
};

struct TheParent
{
    TheParent()
      : mychild(NULL)
      , value(1)
    {
        mychild = new TheChild(*this);
        cout << "TheParent::TheParent() : " << value << endl;
    }

    ~TheParent()
    {
        delete mychild;
    }

    TheChild* mychild;
    int value;
};

TheChild::TheChild(TheParent& parent)
   : myParent(parent)
{
    cout << "TheChild::TheChild() : " << myParent.value << endl;
};


int main()
{
    TheParent parent;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这给了你你可能希望得到的:

TheChild::TheChild() : 1
TheParent::TheParent() : 1
Run Code Online (Sandbox Code Playgroud)

但请注意,如果它TheParent是继承链中的中间类,并且您希望访问尚未构造的派生类中函数的可能被重写的虚拟实现,那么即使这样也会存在问题。

再说一次,最重要的是,如果您发现自己这样做,您可能首先要考虑一下为什么需要这样做。