为基础类构造函数提供初始化的成员

Providing initialized members to base class constructor

本文关键字:初始化 成员 基础类 构造函数      更新时间:2023-10-16

假设我有缺陷的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应该 be-a B,因此它从中继承。但是要初始化B,我们需要A的实例。C必须提供一个,但是如何?在上面的代码中,a用于非专业化,因为基地是在成员面前初始化的。我需要以某种方式在B之前初始化A

如果 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;
};

有更好的方法吗?

您可以使用私人构造函数和指针进行操作:

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与Intanced成员使用相同的语法使用,因为它是参考。如果对您来说还可以,您也可以将m_a留下来,只使用指针m_aPtr