将对成员的引用传递给基类的构造函数

Passing reference to member to constructor of base class

本文关键字:基类 构造函数 引用 成员      更新时间:2023-10-16

我创建了一个依赖项注入,其中a依赖于IB,B1实现IB。对于一个非常特殊的情况,我想创建一个不会公开依赖项注入的类C:a。我想要:

  1. C来构造依赖项并将其传递给它的基类A,从而优雅地处理依赖项的生存期
  2. C可以轻松地向用户公开A的公共方法
class IB
{
public:
virtual void InterfaceCall() = 0;
/* ... */
}
class B1 : IB
{
public:
void IntefaceCall();
/* ... */
}
class A
{
public:
A(IB& ib);
}
// for a specific case I would like to use class A and all it's logic and public methods, but remove dependency injection
class C : A
{
B1 b1;
public:
C()
: A(b1)
, b1() // the order of initialization list is determined by standard
{}
}

这可能吗?或者我需要放弃对C的一个要求吗?

如果A构造函数实际上没有使用引用访问任何成员,我相信这是格式良好的

编辑:A的析构函数也不能使用引用的任何成员,因为值将按相反的顺序析构函数(首先是b1,然后是继承的A(。

在不知道A构造函数和/或析构函数如何通过控制初始化顺序来使用引用的情况下,您可以确保这是一个良好的格式。您可以通过在从A继承之前继承另一个提供b1成员的类型来实现这一点。

以下是我们将继承的类型:

// C++03 version
template <typename T, typename = void>
struct member
{
T value;
};
// C++11 version
template <typename T, typename = void>
struct member
{
T value;
template <typename... Args>
member(Args && ...a) : value{std::forward<Args>(a)...} { }
};

然后,在继承A:之前,我们将让C私下继承它

class IB
{
public:
virtual void InterfaceCall() = 0;
};
class B1 : public IB
{
public:
B1() { std::cout << "constructed B1 " << static_cast<void *>(this) << 'n'; }
virtual void InterfaceCall() { }
};
class A
{
public:
A(IB & ib) { std::cout << "constructed A with B1 " << static_cast<void *>(&ib) << 'n'; }
};
class C : private member<B1>, public A
{
// For convenience, if you need to use the B1 object in C.  If not, you
// can omit this reference.    
B1 & b1;
public:
C() :
member<B1>(), // Implied
A(member<B1>::value),
b1(member<B1>::value) { }
};

证明初始化顺序正确的示例输出:

constructed B1 0x7ffe691b9710
constructed A with B1 0x7ffe691b9710

(演示(


请注意,member模板的第二个参数是一个标记,如果需要,它将允许您使用此技术来控制同一类型的多个成员的初始化顺序。例如,class foo : member<B1, TagA>, member<B1, TagB>