强制成员变量在基类之前构造

时间:2015-10-04 13:47:32

标签: c++ c++11

我目前面临以下情况:

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

如您所见,foobar的设计使用方式如下:

foo f ( /* some parameters */ );
bar b ( f );

但是,如果需要,我希望我的包装类是独立的,derived2需要。但是,derived2::m_foo无法在未初始化的情况下传递给base

所以我的问题是:有没有办法强制derived2::m_foobase之前构建?

我自己提出的唯一解决方案是:

class derived2_foo
{
protected:
    foo m_foo;
};

class derived2 : public base, public derived2_foo
{
public:
    derived2 () : derived2_foo (), base ( m_foo ) {}
};

哪个应该是有效的代码(我可以自由地证明是错误的),但我不太确定我是否想要这个解决方案。所以我在这里寻找其他想法。

1 个答案:

答案 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命名空间在技术上并不隐藏或保护任何内容,但它向客户发出信号,表明他们不应该依赖于其内容。