我目前面临以下情况:
class foo
{
public:
foo ( /* some parameters */ );
};
class bar
{
public:
bar ( foo & f );
};
// both foo and bar are 3rd party
class base
{
public:
base ( foo & f ) : m_bar ( f ) {}
private:
bar m_bar;
};
class derived : public base
{
public:
derived ( foo & f ) : base ( f ) {}
};
class derived2 : public base
{
public:
derived2 () : base ( /* well ... */ ) {}
private:
foo m_foo;
};
如您所见,foo
和bar
的设计使用方式如下:
foo f ( /* some parameters */ );
bar b ( f );
但是,如果需要,我希望我的包装类是独立的,derived2
需要。但是,derived2::m_foo
无法在未初始化的情况下传递给base
。
所以我的问题是:有没有办法强制derived2::m_foo
在base
之前构建?
我自己提出的唯一解决方案是:
class derived2_foo
{
protected:
foo m_foo;
};
class derived2 : public base, public derived2_foo
{
public:
derived2 () : derived2_foo (), base ( m_foo ) {}
};
哪个应该是有效的代码(我可以自由地证明是错误的),但我不太确定我是否想要这个解决方案。所以我在这里寻找其他想法。
答案 0 :(得分:4)
你的基本想法很好,但你应该使用私有继承,以便derived2
的客户不知道里面发生了什么。
class derived2_foo
{
protected:
foo m_foo;
};
class derived2 : private derived2_foo, public base
{
public:
derived2 () : derived2_foo(), base ( m_foo ) {}
};
我还改变了基类在类声明中出现的顺序。始终确保类声明中的顺序与初始化列表中的顺序匹配(就像成员变量一样)。正如C++ FAQ所说:
请注意,B1和B2 [...]的顺序由...决定 基类出现在声明中的顺序 class, not 按初始化程序出现在派生程序中的顺序 class的初始化列表。
或者更为官方的消息来源,§12.6.2/ 13.2的C ++标准:
[...]直接基类按声明顺序初始化 出现在 base-specifier-list 中(无论顺序如何 MEM-初始化)。
另一项改进是将derived2_foo
类放入其自己的“私有”命名空间:
namespace detail
{
class derived2_foo
{
protected:
foo m_foo;
};
}
class derived2 : private detail::derived2_foo, public base
{
public:
derived2 () : derived2_foo(), base ( m_foo ) {}
};
像Boost这样的图书馆也是这样做的。虽然detail
命名空间在技术上并不隐藏或保护任何内容,但它向客户发出信号,表明他们不应该依赖于其内容。