[解決済み] clangの-Wweak-vtablesの意味は何ですか?
質問
私は基本的にclangの
-Wweak-vtables
. 以下は、私がこれまでに観察したことです。
ケース1 (警告が表示されます)
class A {
public:
virtual ~A(){}
};
class B : public A {
public:
virtual ~B(){}
};
int main(){}
ケース2 (警告を表示しない)
class A {
public:
virtual ~A(){}
};
int main(){}
ケース3 (警告を表示しない)
class A {
public:
virtual ~A();
};
A::~A(){}
class B : public A {
public:
virtual ~B(){}
};
int main(){}
ケース4 (警告を表示する)
class A {
public:
virtual ~A(){}
virtual void fun(){}
};
class B : public A {
public:
virtual ~B(){}
};
int main(){}
ケース5 (警告を表示しない)
class A {
public:
virtual ~A(){}
virtual void fun();
};
class B : public A {
public:
virtual ~B(){}
};
int main(){}
ケース6 (警告を表示しない)
class A {
public:
virtual ~A(){}
virtual void fun(){}
};
class B : public A {};
int main(){}
ケース7 (警告が発生しない)
class A {
public:
virtual ~A(){}
virtual void fun(){}
};
class B : public A {
public:
virtual void fun(){}
};
int main(){}
正確な警告は
warning: 'A' has no out-of-line virtual method definitions; its vtable
will be emitted in every translation unit [-Wweak-vtables]
つまり、あるクラスでノンインラインの仮想関数を宣言しなかった場合、そのクラスから派生したクラスが仮想デストラクタを持つ場合に限り、何らかの問題が発生するようです。 派生クラスが仮想デストラクタを持つ場合のみ、何らかの問題が発生するようです。
質問です。
- なぜこれが問題なのですか?
- なぜ仮想関数を宣言することで解決するのでしょうか?(警告は 定義)
- クラスから派生しない場合、なぜ警告が発生しないのですか?
- 派生したクラスが仮想デストラクタを持たない場合、なぜ警告が発生しないのですか?
どのように解決するのですか?
もし、あるクラスのすべての
virtual
メソッドがインラインの場合、コンパイラは vtable の単一の共有コピーを配置する翻訳単位を選択する方法がありません - その代わりに、vtable のコピーはそれを必要とする各オブジェクト ファイルに配置されなければなりません。 多くのプラットフォームでは、リンカは重複する定義を破棄するか、すべての参照を 1 つのコピーにマッピングすることで、これらの複数のコピーを統一することができるため、これは警告にすぎません。
を実装することで
virtual
関数を実装すると、コンパイラはその行外メソッドを実装した翻訳ユニットをクラス実装の詳細のための "home"として選択し、vtable の単一の共有コピーを同じ翻訳ユニットに配置することが可能になります。 複数のメソッドが行外である場合、その選択がクラスの宣言によってのみ決定される限り、コンパイラは任意のメソッドを選択することができます。
もしクラスのどのメソッドもオーバーライドしないのであれば
virtual
キーワードは観察可能な効果を持たないので、コンパイラがそのクラスの vtable を生成する必要はありません。 から派生しない場合は
A
から派生しない場合、あるいは派生クラスのデストラクタを宣言しない場合は
virtual
にはオーバーライドされたメソッドはありません。
A
であり、したがって
A
のvtableは省略されます。 もし、追加で行外の
virtual
メソッドを宣言して警告を抑制し、さらに
A
の実装では、インラインでない
virtual
(の実装(とそれに付随するvtableのコピー)はリンクされた翻訳ユニットで提供される必要があり、さもなければvtableが見つからないためリンクに失敗します。
関連
-
[解決済み】C++コンパイルタイムエラー:数値定数の前に期待される識別子
-
[解決済み】変数 '' を抽象型 '' と宣言できない。
-
[解決済み】'cout'は型名ではない
-
[解決済み】オブジェクト引数のない非静的メンバ関数の呼び出し コンパイラーエラー
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] 文字列の単語を反復処理するにはどうすればよいですか?
-
[解決済み] ルール・オブ・スリーとは?
-
[解決済み] コピーアンドスワップ慣用句とは?
-
[解決済み】C/C++の"-->"演算子とは何ですか?
-
[解決済み】派生クラスでオーバーライドされた関数が、ベースクラスの他のオーバーロードを隠してしまうのはなぜですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】抽象クラス型の無効なnew-expression
-
[解決済み】変数 '' を抽象型 '' と宣言できない。
-
[解決済み】文字列関数で'char const*'のインスタンスを投げた後に呼び出されるterminate [閉店].
-
[解決済み】「corrupted size vs. prev_size」glibc エラーを理解する。
-
[解決済み】C++の変数はイニシャライザーを持っているが、不完全な型?
-
[解決済み】C++プログラムでのコンソールの一時停止
-
[解決済み】オブジェクト引数のない非静的メンバ関数の呼び出し コンパイラーエラー
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み】デバッグアサーションに失敗しました
-
[解決済み】c++で.txtファイルから2次元の配列に読み込む