保护继承和私有继承的类型转换

6
我在学习继承和上/下转型时偶然遇到了这个问题。为什么不允许这样做(代码已注释以显示不允许的部分)?现在我可以猜想为什么不允许,但是一个准确的答案会更好。
至于被允许的代码,我知道这是因为(Base*)是一个C风格的转换,实际上在C++中相当于reinterpret_cast,这意味着在这种情况下它将导致未定义的行为。如果我错了,请纠正我。
class Base
{
};

class Derived : public Base
{
};

class DerivedProt : protected Base
{
};

class DerivedPriv : private Base
{
};

int main()
{
  Base* a = new Derived();
  Base* b = new DerivedProt();  // Not allowed
  Base* c = new DerivedPriv();  // Not allowed

  Base* d = (Base*) new DerivedProt(); // Allowed but undefined behavior...?
  Base* e = (Base*) new DerivedPriv(); // Allowed but undefined behavior...?
}
2个回答

6

标准明确规定 C 风格的强制类型转换可以执行此转换。这是 C 风格强制类型转换唯一可以执行但没有任何 C++ 强制类型转换可以执行的转换。据我所知,其结果不是未定义的;只是其他任何强制类型转换都不允许执行此操作。


1
即使它不是未定义行为,这仍然是一个极其糟糕的想法,应该避免。这种转换非常危险的一点是,即使没有继承关系,编译器也会尝试进行转换,甚至不生成警告。 - Ben Voigt
5
我必须在Comeau在线检查,看看我的编译器是否出错了。不,reinterpret_cast<>也可以做到这一点。 - Hans Passant
@HansPassant 但是 reinterpret_cast 不知道也不关心基类。它不能用于向上或向下转换。 - curiousguy

1

听起来你是正确的。

记住一个事情,传统的OO原则如LSP只适用于公共继承。非公共继承介于继承和组合之间,基类子对象像组合一样是非公共的,但你也可以利用依赖继承的特性,例如虚函数。

然而,就像组成的子对象一样,只有类(或它的后代,在受保护的继承的情况下)可以获取子对象的地址。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接