【问题标题】:Why doesn't a grandchild class's parent handle the initialization of the grandparent class? [duplicate]为什么孙子类的父类不处理祖父类的初始化? [复制]
【发布时间】:2016-11-04 09:21:12
【问题描述】:

我进行了搜索,但找不到我遇到的问题,但也许我只是不知道如何清楚地表达这个问题。

首先,我在相关平台上只有一个 C++98 编译器,所以如果您在回复时请记住这一点,我将不胜感激。

让我举个例子和我得到的错误信息:

namespace mal {

struct Exception : virtual std::runtime_error {
  Exception(): std::runtime_error("mal exception") {}
  explicit Exception(const char* msg): std::runtime_error(std::string(msg?msg:"")) {}
  explicit Exception(const std::string& msg): std::runtime_error(msg) {}
  virtual ~Exception() throw() {}
}; // Exception struct

struct OpenException : virtual Exception {
  OpenException(): Exception("mal open error") {}
}; // OpenException struct

}; // mal namespace

我收到以下错误:

malt.cpp: In constructor ‘mal::OpenException::OpenException()’:
malt.cpp:18: error: no matching function for call to ‘std::runtime_error::runtime_error()’

OpenException 继承 Exception,后者继承 std::runtime_error 并将其初始化为字符串。为什么OpenException初始化语句Exception("mal open error")不使用Exception的const char*重载来初始化std::runtime_error?这不会通过继承层次结构向上传播吗?

如果 C 继承 B,B 继承 A,C 必须了解 A 的实现细节,这似乎与 OO 原则背道而驰。

【问题讨论】:

  • @RSahu 好的,谢谢。我的问题真的与多重继承无关,所以我希望你能把我的“重复”留在这里,以防有人遇到和我一样的问题。我的问题是由虚拟继承引起的;但是,在不知道这一点的情况下,我不会制定一个好的搜索字符串来找到您确定为重复的解决方案。
  • 当然。我没有对你的帖子做任何其他事情。

标签: c++ inheritance exception-handling virtual-inheritance


【解决方案1】:

如果你有一个virtually 继承自基类的类,那么最派生的类总是直接负责调用虚拟基类的构造函数。这是为了防止菱形继承中的问题,即一个类实际上继承自两个类,每个类实际上都从一个共享基类继承。在这种情况下,两个超类中的哪一个应该初始化基类?

请注意,在常规继承中,这不会发生。

【讨论】:

  • 好吧,我想我读到虚拟继承是专门针对多继承菱形效果的最佳实践,如果你有两个类继承 std::runtime_error 并且第三个类继承它们,你的catch (const std::exeception&) 会错过,(...) 会抓住一切。您是否建议:(1)不要在任何一个类(Exception / OpenException)中使用虚拟继承,或者(2)不要在OpenException中使用它,或者(3)继续使用虚拟继承,但吸干并初始化在 OpenException 中再次出现 std::runtime_error,(4) 不同的建议?
  • 除非您确定要使用多重继承,并且您了解这样做的风险,否则我不会使用虚拟继承。您还使用了私有继承,这在这些天是不受欢迎的,可能不是您想要的。
  • 不,我不打算使用多重继承。我刚刚在某处读到(可能是 CERT?),由于钻石问题,这是最佳实践。另外,我打算做公共继承。我认为由于struct 默认情况下是公开的,因此它也适用于继承。我将在其中添加一个明确的public。非常感谢!
  • @Luv2code:“除非你确定要使用多重继承,否则我不会使用虚拟继承”我会走得更远。除非菱形问题对您的用例来说是一个真正的问题,否则不要使用虚拟继承。不仅仅是因为它可能是。
  • 哦,哎呀,错过了这些是结构的事实。但是,是的,除非你真的确定它是你想要的,否则不要使用虚拟继承。就其价值而言,虚拟继承最常见的用途——基本上是我在生产代码中使用的唯一一次——是用于接口类。
猜你喜欢
  • 2020-03-19
  • 2021-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多