为什么保护的继承会导致dynamic_cast失败?

问题描述 投票:3回答:3

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

为什么要将继承更改为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;
   }
};
c++ public protected dynamic-cast
3个回答
6
投票

您作为外部用户,无法访问该课程的受保护成员或私有成员。受保护或私有继承也是如此。类的作者不希望外部用户访问受保护的/私有父类,而不是希望外部用户访问受保护的/私有成员。

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

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

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


2
投票

当您将继承更改为protected时,两个类之间的关系将从对象的外部隐藏起来。


2
投票

私有(或受保护)继承在语义上与公共继承不同。它不是“是”关系,而是“根据”实现的关系。

意味着您不能使用基类作为派生对象的句柄。

© www.soinside.com 2019 - 2024. All rights reserved.