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

Why does protected inheritance cause dynamic_cast to fail?

本文关键字:dynamic cast 失败 受保护 继承 为什么      更新时间:2023-10-16

我将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;
}
};

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

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

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

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

私有(或受保护)继承在语义上与公共继承不同。它不是一种"是-是"关系,而是一种"以某种方式实现"的关系。

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

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