【发布时间】:2017-02-10 17:06:53
【问题描述】:
我正在为我正在开发的 C++ 应用程序编写一个小的异常类层次结构,但我无法从 std::runtime_error 间接派生。这是与我目前所写的代码类似的代码:
class RuntimeException : public virtual boost::exception, public virtual std::runtime_error {
public:
virtual ~RuntimeException() {}
RuntimeException() : runtime_error("A RuntimeException occurred.") {}
RuntimeException(const std::string& what) : runtime_error(what) {}
};
class IllegalArgumentException : public virtual RuntimeException {
public:
IllegalArgumentException() : RuntimeException("An IllegalArgumentException occurred.") {}
IllegalArgumentException(const std::string& what) : RuntimeException(what) {}
};
RuntimeException 类编译没有问题,但IllegalArgumentException 拒绝在 VS2015 上编译,产生错误:no default constructor exists for class "std::runtime_error" 的两个构造函数 IllegalArgumentException。这挑战了我对 C++ 继承层次结构的理解,因为我希望这段代码编译得很好。
我的理解是IllegalArgumentException应该编译,因为尽管std::runtime_error 确实没有默认构造函数,但它的构造函数被RuntimeException 的构造函数调用。但显然这一定是错误的,因为编译器拒绝它。似乎希望我直接从IllegalArgumentException 构造函数调用std::runtime_error 构造函数(当我这样做时编译器错误消失),但这似乎是错误的,因为那时我将调用std::runtime_error 的构造函数两次:一次在RuntimeException 的构造函数中,再次在IllegalArgumentException 的构造函数中。
这样做安全和/或有效吗?如果不是,为什么编译器似乎鼓励它?我可以只是从std::exception 派生并自己将std::string 实现为成员变量,但我认为从已经实现此功能的标准类派生会更容易。这是错误的做法吗?此外,我实际上是从 boost:exception 和 std::runtime_error 派生的事实导致了这个问题吗?
【问题讨论】:
标签: c++ inheritance virtual-inheritance ctor-initializer