当转换到完全不同的类时,static_cast的行为如何? 我在C++中学习了继承和虚拟方法。 所以我发现自己陷入了这样的境地: class A{ public: virtual void f() const {cout << "A::f";} virtual void g() {cout << "A::g"; m();} virtual void h() {cout << "A::h"; f();} void m() {cout << "A::m"; f();} virtual A* n() { cout << "A::n"; return this;} } class B : public A{ public: virtual void f() const {cout << "B::f";} //override void g() {cout << "B::g"; A::n();} //override virtual void m() {cout << "B::m"; f();} A* n() { cout << "B::n"; return this;} } class C : public A{ public: virtual void f() {cout << "C::f";} //new method cause misses const void g() const {cout << "C::g"; m();} //new method cause added const void m() {cout << "C::m"; g(); f();} } *** A*q3 = new C(); (static_cast<B*>(q3->n()))->f(); //solution is A::n A::f *** A类{ 公众: 虚空f()常量{cout

当转换到完全不同的类时,static_cast的行为如何? 我在C++中学习了继承和虚拟方法。 所以我发现自己陷入了这样的境地: class A{ public: virtual void f() const {cout << "A::f";} virtual void g() {cout << "A::g"; m();} virtual void h() {cout << "A::h"; f();} void m() {cout << "A::m"; f();} virtual A* n() { cout << "A::n"; return this;} } class B : public A{ public: virtual void f() const {cout << "B::f";} //override void g() {cout << "B::g"; A::n();} //override virtual void m() {cout << "B::m"; f();} A* n() { cout << "B::n"; return this;} } class C : public A{ public: virtual void f() {cout << "C::f";} //new method cause misses const void g() const {cout << "C::g"; m();} //new method cause added const void m() {cout << "C::m"; g(); f();} } *** A*q3 = new C(); (static_cast<B*>(q3->n()))->f(); //solution is A::n A::f *** A类{ 公众: 虚空f()常量{cout,c++,inheritance,virtual-functions,C++,Inheritance,Virtual Functions,: 静态_cast可以在指向相关对象的指针之间执行转换 类,不仅从派生类到其基,还从 基类到其派生类。这确保至少 如果转换了正确的对象,但未进行安全检查,则兼容 在运行时执行,以检查正在转换的对象是否处于 事实是目标类型的完整对象。因此,它取决于 程序员确保转换是安全的。另一方面, 避免了动态浇铸类型安全检查的开销 您可以很容易地强制转换到比原始对象具有更多字段的对象,尽管您指向的实际对象较短。然后,当您尝试访问这些字段时,这就像缓冲区溢出一样,可能会产生非常令人惊讶的结果。执行此操作时要非常小

静态_cast可以在指向相关对象的指针之间执行转换 类,不仅从派生类到其基,还从 基类到其派生类。这确保至少 如果转换了正确的对象,但未进行安全检查,则兼容 在运行时执行,以检查正在转换的对象是否处于 事实是目标类型的完整对象。因此,它取决于 程序员确保转换是安全的。另一方面, 避免了动态浇铸类型安全检查的开销


您可以很容易地强制转换到比原始对象具有更多字段的对象,尽管您指向的实际对象较短。然后,当您尝试访问这些字段时,这就像缓冲区溢出一样,可能会产生非常令人惊讶的结果。执行此操作时要非常小心。

这会将
C*
对象强制转换为
a*
对象(通过
n()
)然后将
A*
对象强制转换为
B*
对象。最后它调用虚拟函数

那么实际上会发生什么呢?编译器将查看底层对象的虚拟表,并在那里找到要调用的函数
f
。虚拟表是内存中的实际表。因此,从A到B到C的所有转换都不会影响表中的数据。 没有未定义的行为,实际上将调用
A::f


<>但是,这只适用于<强>虚函数>。如果代码使用C对象调用B的成员函数,如果该函数使用B中可用的成员数据,而不是C中的所有成员,则所有地狱都会松开。欢迎C++,在这里,在脚中射击自己的能力是期望的特性。“那么这是书中的错误还是正确的?“-这本书到底说了什么?
这是书中的错误吗
这类代码在书中吗?你介意分享这本书是什么吗?代码不编译此练习的目的是告诉输出是什么:如果它编译了,那么控制台输出中会出现什么,如果不复制,则将其设置为“NC”,如果有运行时错误/未定义的行为,则标记为“?”。我没有这本书,它是我的教授共享的部分(我不知道名称或其他),我评论的是提供的解决方案。对于UB声明不太确定。标准在[expr.static.cast](C++17:5.2.9(11)):“如果“指向cv1 B的指针”指向一个B,该B实际上是类型D对象的子对象,结果指针指向类型D的封闭对象。否则,行为未定义。“我理解为:该对象必须是强制转换类型或派生类型,否则将调用UB。”在存在一个似乎是合理要求的设备化优化器的情况下。但是如果这项工作是出于您解释的原因,那么对于这个?
(static_cast(q2))->g();//解决方案是“”(未定义的行为/运行时错误)
其中q2是
a*q2=new B()
我想我会回答自己再次阅读此
如果代码使用C对象调用B的成员函数,并且如果该函数使用B中可用的成员数据,而不是C中可用的成员数据,那么所有的麻烦都会爆发出来