如何防止使用尚未构建的类成员?

时间:2012-10-26 17:25:25

标签: c++ constructor

我有以下课程:

class A
{
public:
    A() { x = 0; std::cout<<"A default ctor()\n"; }
    A(int x_) { x = x_; std::cout<<"A normal ctor()\n"; }
    int x;
};

class B
{
public:
    B() { std::cout<<"B ctor()\n"; }
private:
std::string str;
};

和创建对象B的函数,将对象A作为参数:

B
createB(const A& a) {
    std::cout<<"a int: "<<a.x<<"\n";
    return B();
}

如果我设计了一个类C,它具有类型A和B的成员并在构造A-object之前构造B对象但是使用A对象这样做,这将编译警告,但它会默默输入一个错误:

class C
{
public:
    C(): b(createB(a)), a(10) {}
private:
    B b;
    A a;
};


int main()
{
    C c;
    return 0;
}

当然,上面的例子是一个微不足道的例子,但我在现实世界中看到它,在更复杂的代码中(它是星期五,晚上8:30,我刚刚解决了导致段错误的错误)。 / p>

如何防止这种情况发生?

2 个答案:

答案 0 :(得分:2)

我同意其他人的建议,即设计师有责任确保在使用前初始化对象。在你的情况下,我看到两种方法:

首先(也是最简单的),颠倒类定义中ab的顺序:

class C
{
public:
    C(): b(createB(a)), a(10) {}
private:
    A a;
    B b;
};

其次,如果你想真的强调它的初始化发生在其他成员的初始化之前,你可以将a移动到基类:

class CBase
{
protected:
    CBase(): a(10) {}
protected:
    A a;
};

class C : private CBase
{
public:
    C(): b(createB(a)) {}
private:
    B b;
};

答案 1 :(得分:0)

我看到三种可能的选择:

在构建A

之前需要构建C
class C
{
public:
   C(const A& a) : a_(a), b_(a) {}
private:
   A a_;
   B b_;
};

在构建'B'之前构造A

延迟B的构建,直到A完成。这会阻止未定义的行为发生,但不会通过接口强制执行正确的行为(如选项1和3 执行

class C
{
public:
   C() : a_(/* construct as appropriate */)
   {
      b_.reset(new B(a_));
   }

private:
   A a_;
   std::unique_ptr<B> b_;
};

如果设计允许,请B包含(并公开)A

这似乎可以从简单的例子中得出,但在现实生活中可能不是:

class B
{
public:
   const A& my_a() {return a_;}
private:
   // construct as appropriate (?)
   A a_;
};

class C
{
private:
   B b_;
};