继承构造函数和虚拟基类

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

#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();
}

所有的构造函数都应该与ExceptionBase类的构造函数相同。 派生的异常仅在其类型方面有所不同,否则不会有其他功能。 上面代码中提到的最后一个异常类型也应该有这些构造函数。 这可能使用C ++ 11标准的继承构造函数吗? 如果这是不可能的:什么是替代品?

(顺便说一下:在上面的代码中,类OperationFailureFileDoesNotExistError没有用gcc 4.8编译,但是用了3.4编译。显然,gcc拒绝继承虚拟基础的构造函数,知道谁在这里很有趣。类OperationFailedBecauseFileDoesNotExistError ,因为继承构造函数不从直接基地继承。)


当using-declaration用于继承构造函数时,它需要一个直接的基类[namespace.udecl] / 3

如果这样的使用声明指定了一个构造函数,那么嵌套名称说明符应该指定被定义类的直接基类; 否则它会引入通过成员名称查找找到的一组声明。

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

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


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

//using ExceptionBase::ExceptionBase;

OperationFailure(char const * msg)
: ExceptionBase( static_cast<const char*&&>(msg) )
{}

由于您只能初始化mem-initializer-list中的直接基类(或虚拟基类),因此非虚拟基类将using-declaration限制为仅从直接基类继承ctors是有意义的。

继承Ctors提案的作者已经意识到这打破了对虚拟基类的支持,请参阅N2540:

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


创建构造函数就像为所有指定的构造函数引入了包装函数。 在你的情况下,你必须调用OperationFailureFileDoesNotExistError的具体构造函数,但引入的包装只会调用其中任何一个。


我刚刚检查了最新的C ++ 11草案(第12.9节),但它并未真正明确地涵盖您的案例。

链接地址: http://www.djcxy.com/p/78939.html

上一篇: Inheriting constructors and virtual base classes

下一篇: Multiple instances of a virtual base class subobject (really)