在 C++ 中,为什么可以强制转换为派生类型的引用?

Raj*_*sad 5 c++ inheritance casting reference derived-instances

准确地说,为什么下面的程序可以B b = (B&) a编译并运行,而B b = (B) a不能?

#include <iostream>
using namespace std;

class A {public: void f(){ cout<<"A"<<endl;} };

class B : public A { public: void f(){cout<<"B"<<endl;} };

void g(A a){  B b = (B&) a; b.f(); }

int main() {
    B b; g(b);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

是否有关于转换为派生类型以及我在这里缺少的参考的内容?如果我只是强制转换为 B,则会出现编译时错误:构造函数 B(A a) 不存在。

Vio*_*ffe 5

A因为从到 的隐式转换B不存在,并且您也没有定义显式转换。

另一方面,引用转换是有效的,因为继承类型允许它。更准确地说,您可以在同一继承层次结构中的不同类之间进行两种方式的转换。指针也是如此。如果您需要一些进一步研究的指导,相关概念称为多态性。

但请注意,只有将类型转换为对象才有意义。例如:BB

B b;
A& aRef = B; // equivalent of A& ref = (A&)B;
B& bRef = (B&)aRef;
Run Code Online (Sandbox Code Playgroud)

一旦您尝试B访问A. 因为你的实际对象是A,不是B

向上转换(从后代到上升)始终是安全的,因为继承基类的类的任何对象都是有效的基对象。然而,由于我上面解释的确切原因,向下转型是危险的,并且永远不应该使用 C 风格的转型来完成。相反,使用dynamic_cast

B b;
A& aRef = B;
B& bRef = dynamic_cast<B&>(aRef);
Run Code Online (Sandbox Code Playgroud)

dynamic_cast使用 RTTI(运行时类型信息)来验证操作,std::bad_cast如果转换无效,将抛出异常。这与dynamic_casting 指针不同,在这种情况下,强制转换会返回nullptr而不是抛出异常。