c++ - 为什么 protected 继承会导致 dynamic_cast 失败?

标签 c++ public protected dynamic-cast

我将我的 C++ 基类更改为 protected 继承并且我的 dynamic_cast(s) 停止工作。

为什么将继承更改为 protected 会改变 dynamic_cast 的行为?

struct Base {
  static Base *lookupDerived(); // Actually returns a Derived * object.
};

struct Derived : protected /* Switch this to public to get it working */ Base {
 static void test() {
   Base *base = lookupDerived();

   if (dynamic_cast<Derived *>(base)) {
      std::cout << "It worked (we must be using public inheritance)." << std::endl;
   } else {
      std::cout << "It failed (we must be using protected inheritance)." << std::endl;
   }
};

最佳答案

作为外部用户,您无法访问类的 protected 或私有(private)成员。这同样适用于 protected 或私有(private)继承。类的作者不希望外部用户访问 protected /私有(private)父类,正如他们不希望外部用户访问 protected /私有(private)成员一样。

原因之一:假设父类有一个非虚析构函数。从基类指针的实例派生类中删除将导致未定义的行为。使父类 protected /私有(private)意味着您不能这样做(参见脚注)。

另一个原因:假设相关类的作者不希望外部用户访问父类的公共(public)成员。可以使用公共(public)继承 (is-a) 并将这些公共(public)接口(interface)降级为 protected 或私有(private)接口(interface),但这会违反 Liskov 替换原则。 protected 或私有(private)继承不是是一个 关系。这些公共(public)方法通过 protected 或私有(private)继承而变得 protected 或私有(private)。 Liskov 替换没有问题,因为 protected /私有(private)继承不是is-a

脚注:有一个丑陋的解决方法:使用 C 风格的转换。外部用户可以投 派生类指针指向基类指针,即使基类不可访问。对我来说,这是使用 -Wold-style-cast -Werror 进行编译的另一个原因。

关于c++ - 为什么 protected 继承会导致 dynamic_cast 失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12765174/

相关文章:

java - Circle 函数在 Java 类中的行为不符合预期

c++ - 注意事项 "protected versus private"

c++ - 为什么派生类不能通过指向基类的指针访问其基类的 protected 成员?

c++ - 在 C++ 中通过赋值初始化自己的 String 类

c++ - sockaddr、sockaddr_in 和 sockaddr_in6 有什么区别?

c++ - 是否有可能调用 WriteFile 并且应用程序将永远等待回调?

java - 类和对象的基础知识 : Java

c++ - 使用 QT 创建共享 c 库

Objective-C 静态、外部、公共(public)变量

scala - 如何解决 "Implementation restriction: trait ... accesses protected method ... inside a concrete trait method."