次の単純な状況を考えてみましょう:
A.h
class A {
public:
virtual void a() = 0;
};
B.h
#include <iostream>
class B {
public:
virtual void b() {std::cout << "b()." << std::endl;};
};
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;
}
言い換えれば:
- A は純粋な仮想クラスです。
- B は、スーパー クラスがなく、非純粋仮想関数が 1 つあるクラスです。
- C は A および B のサブクラスであり、A の純粋仮想関数をオーバーライドします。
私を驚かせたのは、最初の出力です。
((A*) b)->a(); // Output: b().
コード内で a() を呼び出していますが、 b() が呼び出されます。私の推測では、変数 b がクラス A のサブクラスではないクラス B へのポインターであるという事実に関連していると思いますが、それでもランタイム型は C インスタンスへのポインターです。
Javaの観点から、これを説明する正確なC++ルールは何ですか?奇妙な動作?