4

我有以下课程:

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 对象之前构造 B 对象,但使用 A 对象这样做,这将在没有警告的情况下编译,但它会默默地输入一个错误:

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


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

当然,上面的例子是一个微不足道的例子,但我在现实世界中看到过它,代码要复杂得多(现在是星期五,晚上 8:30,我刚刚修复了这个导致段错误的错误)。

我怎样才能防止这种情况发生?

4

2 回答 2

2

I would agree with what others have suggested, namely that the onus is on the designer to ensure that objects are initialized before use. I see two ways of doing that in your case:

First (and easiest), reverse the order of a and b in the class definition:

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

Second, you could move a to a base class if you want to really emphasize that it's initialization occurs before that of other members:

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

class C : private CBase
{
public:
    C(): b(createB(a)) {}
private:
    B b;
};
于 2012-10-26T18:05:50.103 回答
0

我看到了三种可能的选择:

要求A在建造之前建造C

class C
{
public:
   C(const A& a) : a_(a), b_(a) {}
private:
   A a_;
   B b_;
};

在构造A“B”之前构造:

延迟构建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_;
};
于 2012-10-26T17:35:42.187 回答