将初始化成员提供给基类​​构造函数

时间:2017-12-09 07:30:40

标签: c++ initialization

让我们说我这样的C ++代码有缺陷:

struct A final {
    A(); // Initializes somethingShared

    shared_ptr<Something> somethingShared;
};

struct B {
    B(const A& a);
};

struct C : B {
    C()
    : B(a) {} // Uh-oh

    A a;
};

C B,因此它会从中继承。但要初始化B,我们需要一个A的实例。 C必须提供一个,但如何?在上面的代码中,a未初始化使用,因为base在成员之前初始化。我需要在A之前以某种方式初始化B

如果A 不是 final,我可以私下从A继承:

struct C : private A, public B {
    C()
    : B(*this) {}
};

但是因为它是final,我这样做:

namespace detail {
    struct C_Base {
    protected:
        A a;
    };
}

struct C : private detail::C_Base, public B {
    C()
    : B(detail::C_Base::a) {}
};

或者我可以使用这样的怪异黑客:

struct C : B {
    C(const A a = A())
    : B(a),
      a(a) {}

    A a;
};

有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

您可以使用私有构造函数和指针来执行此操作:

class C : B {
private:
    const std::unique_ptr<A> m_aPtr;
    C(A* a) : B(*a) , m_aPtr(a), m_a(*a){}
public:
    C() : C(new A()) {}

    A& m_a;
};

这将确保

  • A在构建B
  • 之前已完全构建
  • A仅构建一次而不是复制
  • m_aPtr将在课程的生命周期内保持有效(由于const)并且会在类毁坏时正确销毁A(如实例成员)
  • 您可以使用m_a语法与实例成员相同,因为它是一个引用。如果它对您没问题,您也可以离开m_a并仅使用指针m_aPtr