Mar*_*arc 7 c++ polymorphism virtual-functions
考虑这种简单的情况:
A.h
class A {
public:
virtual void a() = 0;
};
Run Code Online (Sandbox Code Playgroud)
B.h
#include <iostream>
class B {
public:
virtual void b() {std::cout << "b()." << std::endl;};
};
Run Code Online (Sandbox Code Playgroud)
C.h
#include "A.h"
#include "B.h"
class C : public B, public A {
public:
void a() {std::cout << "a() in C." << std::endl;};
};
int main() {
B* b = new C();
((A*) b)->a(); // Output: b().
A* a = new C();
a->a(); // Output:: a() in C.
return 0;
}
Run Code Online (Sandbox Code Playgroud)
换句话说:
- A是纯虚拟类.
- B是一个没有超类和一个非纯虚函数的类.
- C是A和B的子类,并覆盖A的纯虚函数.
令我惊讶的是第一个输出即
((A*) b)->a(); // Output: b().
Run Code Online (Sandbox Code Playgroud)
虽然我在代码中调用了(),但是调用了b().我的猜测是,它与变量b是指向类B的指针这一事实有关,而B类不是类A的子类.但运行时类型仍然是指向C实例的指针.
从Java的角度来看,解释这个问题的确切C++规则是什么,奇怪的行为?
i_a*_*orf 24
你是无条件地浇铸b到一个A*使用C样式转换.编译器不会阻止你这样做; 你说它是一个A*所以它是一个A*.因此它将它指向的内存视为一个实例A.因为a()是Avtable中列出的第一个方法,并且b()是vtable中列出的第一个方法B,当你调用a()一个真正的对象时B,你就得到了b().
你很幸运,对象布局是相似的.这不能保证是这种情况.
首先,你不应该使用C风格的演员表.你应该使用更安全的C++强制转换操作符(虽然你仍然可以用脚射击自己,所以仔细阅读文档).
其次,除非你使用,否则你不应该依赖这种行为dynamic_cast<>.
sth*_*sth 11
在多重继承树中进行投射时,请勿使用C样式转换.如果您使用,dynamic_cast则获得预期结果:
B* b = new C();
dynamic_cast<A*>(b)->a();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4826 次 |
| 最近记录: |