我目前面临以下情况:
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 ) {}
};
哪个应该是有效的代码(我可以随意证明是错误的),但是我不确定我是否喜欢这种解决方案。因此,我在这里寻求其他想法。
最佳答案
您的基本想法是一个好主意,但是您应该使用私有(private)继承,以便derived2
的客户端不知道内部发生了什么。
class derived2_foo
{
protected:
foo m_foo;
};
class derived2 : private derived2_foo, public base
{
public:
derived2 () : derived2_foo(), base ( m_foo ) {}
};
我还更改了基类在类声明中出现的顺序。始终确保类声明中的顺序与初始化列表中的顺序匹配(就像成员变量一样)。正如C++ FAQ所说:
或什至更正式的资料,请参见§12.6.2/ 13.2的C++标准:
另一个改进是将
derived2_foo
类放入其自己的“私有(private)” namespace :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
命名空间从技术上讲不会隐藏或保护任何内容,但它会向客户端发出信号,表明它们不应依赖于其内容。