向基类构造函数提供初始化成员

3

假设我有以下有缺陷的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 没有初始化,因为基类在成员之前初始化。我需要在初始化 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;
};

有更好的方法吗?


你可以在 struct B 中包含 A a,并将其实例传递给 B 的构造函数,例如:B(const A& _a) : a(_a),从 C 的构造函数中调用:C(const A& a = A()) : B(a) { } 或者 C() : B(A)) { } - rosengrenen
最好的方法是重写“C”,使其不需要一个“A”数据成员或者不需要继承自“B”。所有其他解决方案,包括如果“A”不是最终版本可能会出现的解决方案,都会使代码难以阅读和理解。 - Christian Hackl
我无法更改 ABC 需要一个 A 成员,并且需要继承自 B。我正在寻找满足这些限制条件的解决方案。 - basteln
1个回答

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

这将确保:
  • 在构造B之前,A已完全构造
  • A仅构造一次且不被复制
  • m_aPtr由于const的存在,将在类生命周期内保持有效,并在类销毁时正确地销毁A(就像一个实例成员)
  • 您可以使用与实例成员相同的语法使用m_a,因为它是一个引用。如果您愿意,也可以省略m_a并仅使用指针m_aPtr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接