继承构造函数和虚拟基类

Ral*_*zky 6 c++ virtual-inheritance c++11 inheriting-constructors

我即将创建一个异常类层次结构,概念上看起来像这样:

#include <iostream>
#include <stdexcept>

class ExceptionBase : public std::runtime_error {
public: 
    ExceptionBase( const char * msg ) : std::runtime_error(msg) {}
};

class OperationFailure : virtual public ExceptionBase {
public: 
    using ExceptionBase::ExceptionBase;
};

class FileDoesNotExistError : virtual public ExceptionBase {
public: 
    using ExceptionBase::ExceptionBase;
};

class OperationFailedBecauseFileDoesNotExistError
    : public OperationFailure, FileDoesNotExistError {
public: 
    using ExceptionBase::ExceptionBase; // does not compile
};

int main() {
    OperationFailedBecauseFileDoesNotExistError e("Hello world!\n");

    std::cout << e.what();
}
Run Code Online (Sandbox Code Playgroud)

所有构造函数应该与ExceptionBase类的构造函数相同.派生的异常仅在类型上有所不同,否则没有添加的功能.上面代码中提到的最后一个异常类型也应该有这些构造函数.这是否可以使用C++ 11标准的继承构造函数功能?如果那是不可能的:还有什么选择?

(顺便说一句:在上面的代码中的类OperationFailureFileDoesNotExistError.没有用gcc 4.8编译,但铿锵3.4显然,海湾合作委员会拒绝为虚拟基础继承构造函数这将是有趣的,知道谁在这里两种编译器拒绝了类OperationFailedBecauseFileDoesNotExistError,因为继承构造函数不从直接基础继承.)

dyp*_*dyp 2

使用using声明继承构造函数时,需要直接基类[namespace.udecl]/3

如果这样的using 声明命名了构造函数,则嵌套名称说明符应命名所定义的类的直接基类;否则它会引入通过成员名称查找找到的声明集。

也就是说,在您的情况下,using 声明OperationFailedBecauseFileDoesNotExistError不会继承,而是重新声明(作为别名)或取消隐藏 的 ctor 的名称ExceptionBase

您必须为 编写一个非继承 ctor OperationFailedBecauseFileDoesNotExistError


顺便说一句,这对于非虚拟基类来说很好:继承 ctor 的 using 声明被重写为:

//using ExceptionBase::ExceptionBase;

OperationFailure(char const * msg)
: ExceptionBase( static_cast<const char*&&>(msg) )
{}
Run Code Online (Sandbox Code Playgroud)

由于您只能在mem-initializer-list中初始化直接基类(或虚拟基类) ,因此对于非虚拟基类来说,限制using 声明仅从直接基类继承构造函数是有意义的。

继承 ctors 提案的作者已经意识到这会破坏对虚拟基类 ctors 的支持,请参阅N2540

通常,继承具有虚拟基的类的构造函数定义将是错误的,除非虚拟基支持默认初始化,或者虚拟基是直接基,并命名为转发到的基。同样,所有数据成员和其他直接基数必须支持默认初始化,否则任何使用继承构造函数的尝试都将是错误的。注意:使用时格式错误,未声明。