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

标签 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 );

但是,如果需要,我希望我的包装类是独立的,并且 衍生2 需要是独立的。但是,衍生2::m_foo不能在未初始化时直接传递给base

所以我的问题是:有没有办法强制 衍生2::m_foobase 之前构造?

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

class derived2_foo
{
protected:
    foo m_foo;
};

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

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

最佳答案

您的基本想法是好的,但您应该使用私有(private)继承,以便 衍生2 的客户端不知道内部发生了什么。

class derived2_foo
{
protected:
    foo m_foo;
};

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

我还更改了基类在类声明中出现的顺序。始终确保类声明中的顺序与初始化列表中的顺序匹配(就像成员变量一样)。作为C++ FAQ说:

Note that the order B1 and then B2 [...] is determined by the order that the base classes appear in the declaration of the class, not in the order that the initializer appears in the derived class’s initialization list.

或者对于更官方的来源,C++ 标准位于 §12.6.2/13.2:

[...] direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).

另一个改进是将衍生2_foo类放入它自己的“私有(private)”命名空间中:

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

关于c++ - 强制在基类之前构造成员变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32934179/

相关文章:

c++ - 为共享库加载 gdb 源

android - 无法使用 nfc_initiator_transceive_bytes() 通过 libnfc 发​​送大型 APDU 命令

c++ - Qt Creator 使用位于另一个地方的另一个 GCC 版本

c++ - STL map 和 set 中的排序顺序

c++ - 一种动态分配多维数组的方法

c++ - Clang 和 Intel 无法编译此 CRTP 代码

c++ - 使用值初始化数组对数据进行零初始化

c++ - 在 C++ 中将指针数组的所有元素设置为 nullptr

c++ - 使用正则表达式进行范围检查?

c++ - 没有参数列表时模板名称 ‘boost::asio::strand’ 的使用无效