从没有默认构造函数的虚拟基派生 class
Deriving class from virtual base with no default constructor
我正在为我正在开发的 C++ 应用程序编写一个小的异常层次结构 classes,但我无法从 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
class 编译没有问题,但是 IllegalArgumentException
拒绝在 VS2015 上编译,生成错误: no default constructor exists for class "std::runtime_error"
for both constructors of IllegalArgumentException
.这挑战了我对 C++ 继承层次结构的理解,因为我希望这段代码可以正常编译。
我的理解是 IllegalArgumentException
应该 编译,因为尽管 std::runtime_error
确实没有默认构造函数,但它的构造函数正在被调用通过 RuntimeException
的构造函数。但显然这一定是错误的,因为编译器拒绝了它。似乎要我直接从 IllegalArgumentException
构造函数调用 std::runtime_error
构造函数(当我这样做时编译器错误消失),但这似乎是错误的,因为那样我会调用构造函数 std::runtime_error
两次:一次在 RuntimeException
的构造函数中,另一次在 IllegalArgumentException
.
的构造函数中
这样做安全and/or吗?如果不是,为什么编译器似乎鼓励它?我 可以 只是从 std::exception
派生并将 std::string
自己实现为成员变量,但我认为从标准 [=42= 派生会更容易] 已经实现了这一点。这是错误的做法吗?此外,我实际上从 boost:exception
和 std::runtime_error
中得出的事实是否导致了这个问题?
当使用 virtual
继承时,virtual
基础的构造函数调用是 most derived class 的责任而不是责任任何中间体 class。原因很明显:使用 virtual
继承表示期望实际上有多个派生 class 使用基 class。这些派生的 classes 中的哪一个将负责构建 virtual
基础?
因此,任何派生的 classes 的构造函数都需要为 virtual
基提供一个参数,例如:
IllegalArgumentException::IllegalArgumentException(std::string const& what)
: std::runtime_error(what)
, RuntimeException(what) {
}
为了避免中间基调用 virtual
基 class 的构造函数,用于 virtual
继承通常会提供默认构造函数。当然,这开启了最派生的 class 错误地依赖于其基础之一调用的正确构造函数的可能性。
我正在为我正在开发的 C++ 应用程序编写一个小的异常层次结构 classes,但我无法从 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
class 编译没有问题,但是 IllegalArgumentException
拒绝在 VS2015 上编译,生成错误: no default constructor exists for class "std::runtime_error"
for both constructors of IllegalArgumentException
.这挑战了我对 C++ 继承层次结构的理解,因为我希望这段代码可以正常编译。
我的理解是 IllegalArgumentException
应该 编译,因为尽管 std::runtime_error
确实没有默认构造函数,但它的构造函数正在被调用通过 RuntimeException
的构造函数。但显然这一定是错误的,因为编译器拒绝了它。似乎要我直接从 IllegalArgumentException
构造函数调用 std::runtime_error
构造函数(当我这样做时编译器错误消失),但这似乎是错误的,因为那样我会调用构造函数 std::runtime_error
两次:一次在 RuntimeException
的构造函数中,另一次在 IllegalArgumentException
.
这样做安全and/or吗?如果不是,为什么编译器似乎鼓励它?我 可以 只是从 std::exception
派生并将 std::string
自己实现为成员变量,但我认为从标准 [=42= 派生会更容易] 已经实现了这一点。这是错误的做法吗?此外,我实际上从 boost:exception
和 std::runtime_error
中得出的事实是否导致了这个问题?
当使用 virtual
继承时,virtual
基础的构造函数调用是 most derived class 的责任而不是责任任何中间体 class。原因很明显:使用 virtual
继承表示期望实际上有多个派生 class 使用基 class。这些派生的 classes 中的哪一个将负责构建 virtual
基础?
因此,任何派生的 classes 的构造函数都需要为 virtual
基提供一个参数,例如:
IllegalArgumentException::IllegalArgumentException(std::string const& what)
: std::runtime_error(what)
, RuntimeException(what) {
}
为了避免中间基调用 virtual
基 class 的构造函数,用于 virtual
继承通常会提供默认构造函数。当然,这开启了最派生的 class 错误地依赖于其基础之一调用的正确构造函数的可能性。