「vtableへの未定義参照」エラーメッセージを扱うスタックオーバーフローに関する他の質問があります。次のコードは、引数なしのコンストラクター C() がインラインで実装されているかどうかに応じて、コンパイルされるか、コンパイルされません。メンバー関数 m() は純粋な仮想でなければならず、問題を修正するために行う正しい変更であることはわかっています。私にとって紛らわしいのは、明らかに無関係な変更でコンパイルできることです。
次のコードは、g++ (ubuntu 64 ビットの 4.6.3) でコンパイルされず、予期される「C の vtable への未定義参照」メッセージを生成します (これは、問題が m() にあることを考えると、依然としてひどいエラー メッセージです)。
Header.h
#ifndef HEADER_H
#define HEADER_H
class C
{
public:
C();
virtual void m();
};
#endif
実装.cpp
#include "Header.h"
C::C() {}
メイン.cpp
#include "Header.h"
int main()
{
return 0;
}
次の無関係な変更により、コンパイルが可能になります。
- C::C() の非インライン実装を Implementation.cpp から削除
- C() の単純なインライン実装を Header.h のクラスに追加します。
なぜこれがコンパイルを許可するのですか? これはコンパイラのバグですか、オプティマイザの問題ですか、それとも標準的な驚きの暗い隅ですか?