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

时间:2012-10-07 00:51:22

标签: 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;
   }
};

3 个答案:

答案 0 :(得分:4)

您作为外部用户无法访问类的受保护或私有成员。这同样适用于受保护或私有继承。类的作者不希望外部用户访问受保护/私有父类,而不希望外部用户访问受保护/私有成员。

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

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

脚注:有一种丑陋的方式:使用C风格的演员表。外面的用户可以投了一个 派生类指向基类指针的指针,即使基类不可访问。对我而言,这是使用-Wold-style-cast -Werror编译的另一个原因。

答案 1 :(得分:1)

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

答案 2 :(得分:1)

私有(或proctected)继承在语义上与公共继承不同。 它不是“是一种”关系,而是一种“以”关系实施“。这意味着您无法使用基类作为派生对象的句柄。