なぜオーバーライドは実行時に解決されますが、オーバーロードはコンパイル時に解決されますか?
は、コンパイル時にオーバーライドが解決される理由があります。C++オーバーロードとオーバーライドの解決時間
答えて
コンパイル時にオーバーライドが解決される理由はありますか。期待どおり多型の話をしていると仮定すると、
は、すなわち
#include <iostream>
class Base
{
public:
virtual void Foo()
{
std::cout << "Base::Foo()" << std::endl;
}
};
class Derived : public Base
{
public:
virtual void Foo()
{
std::cout << "Derived::Foo()" << std::endl;
}
};
上記のコードが動作するように、このようなことを可能にする:
void CallFoo(Base& b)
{
b.Foo();
}
int main()
{
Base b;
Derived d;
CallFoo(b); // calls Base::Foo()
CallFoo(d); // Calls Derived::Foo();
}
CallFoo()
は何も知らないことを認識することが重要ですBase
インスタンスまたはDerived
インスタンスを指している可能性があります。すべてCallFoo()
getsはBase
への参照です。実際に何が参照されているかについては何も言わないので、コンパイラがコンパイル時にどのように解釈できるかはわかりません。CallFoo()
したがって、Base::Foo()
またはDerived::Foo()
を呼び出す必要があるかどうかを判断することは、実行時の決定である必要があります。
virtual
キーワードを削除すると(オーバーライドを無効にする)上記のコードでBase::Foo()
が2回表示され、Base::Foo()
ではなくDerived::Foo()
ではありません。これは、virtual
キーワードがないと、コンパイラはコンパイル時にBase::Foo()
への呼び出しを解決するためです。
コンパイラは、実際にはb
のタイプを把握するためにできるだけオーバーフローが発生します(つまり、呼び出す必要のある適切な関数は実行時の決定であるため) 。その場合、コンパイル時の決定になります。しかし、それは実装の詳細です。
オーバーライドは、仮想関数の実行時に解決されるのは、dynamic bindingが達成されるためです。非仮想関数呼び出しは、コンパイル時に解決されます。
なぜオーバーライドは実行時に解決されますが、オーバーロードはコンパイル時に解決されますか?
実際はそれに依存します。
通常、オーバーライドの場合、コンパイラは実行時まで呼び出される実際の関数を特定できません。これは、実行時までBaseクラスポインタが認識されない実際のオブジェクトが存在するためです。このような場合、コンパイラにはオプションがありませんが、実際の関数呼び出しは実行時に解決されます。
しかし、時にはコンパイラはオーバーライドの際にも呼び出す必要がある関数を賢明に&検出できます。そのようなシナリオではコンパイル時に呼び出される関数を解決できます。
オーバーロードの場合、呼び出される実際の関数は、関数に渡されるパラメータだけに基づいてコンパイラによって決定されるため、コンパイラは実行時まで実行を待つ必要はありません。 C++は静的型言語であるため、コンパイル時にはすべての型を知っておく必要があります。
'オーバーライドした場合でもコンパイラが呼び出す必要のある関数をスマートに&決定的に検出することがありますこの例がありますか? –
@Jesse:チェックアウト:[コンパイラはいつ静的に呼び出しを仮想関数にバインドできますか?](http://stackoverflow.com/questions/7291596/when-can-the-compiler-statically-bind-a-call仮想関数)、そして、私が引用したものは、実証済みの事実です。ここに推測はありません。 –
リンクありがとう! –
C++での関数のオーバーロードは、コンパイラ自体で処理できます。関数のオーバーロード中、コンパイラは技術的にはname mangling
と呼ばれる関数名を「装飾」します。したがって、生成されたコードでは、各オーバーロードされたメソッドは別の名前を持ちます。このようにコンパイラはコンパイル時にどのメソッドを呼び出すかを知っています。
関数のオーバーライドの場合(派生クラスはその基本クラスのメソッドを再定義する)、基本クラスのメソッドが非仮想の場合、呼び出す関数はコンパイル時に決定されます。しかし、それが仮想関数であれば、コンパイラはコンパイル時にコールを解決できません。仮想テーブル参照は、オブジェクト内の仮想ポインタを介して行わなければならない。これは、実行時にのみ発生する可能性があります。実行時には、どのオブジェクトを扱っているのか知ることができるからです。
- 1. C++否定し、オーバーロードの解決
- 2. C#からオーバーライドされオーバーロードされたF#メソッドを解決できません
- 3. C++でのオーバーライドとオーバーロードの同時実行
- 4. Haskellの "未解決のオーバーロード"
- 5. modfのオーバーロードの解決
- 6. 関数テンプレートのオーバーロード解決
- 7. 「オーバーロード解決のあいまいエラー」は別のオーバーロードで解決しました
- 8. C++ 11のコンストラクタのオーバーロードの解決とinitialiser_lists:clang ++とg ++の同意がない
- 9. C++のオーバーロードの解決、ユーザ定義の変換機能、テンプレート
- 10. オーバーロード時のC++コンパイルエラー
- 11. C++未解決のオーバーロードされた関数型
- 12. C++ <未解決のオーバーロードされた関数タイプ>
- 13. ref-qualifierでのオーバーロードの解決
- 14. Typescript:数値の関数オーバーロード解決| ArrayBuffer
- 15. Java Joda時間isAfter日付解決
- 16. はスウィフト3クロージャがオーバーロード解決
- 17. 「オーバーロード解決エラー」を返すSQLクエリ
- 18. 関数テンプレートポインタ引数でオーバーロード解決
- 19. 関数のオーバーロード時のオーバーロード時のエラーcmath関数C++
- 20. C++でヘッダーファイルをインクルードするときに間違ったオーバーロードを解決する方法
- 21. オーバーロードの解決とconstへの共有ポインタ
- 22. オーバーロードの解決、名前検索と関数ポインタ
- 23. Kotlin:インラインラムダとオーバーロード解決のあいまいさ
- 24. グラフィックエディタのプログラミングの課題解決の時間制限を超えましたC++
- 25. C++テンプレートのオーバーロードの解決には、テンプレートのインスタンス化の後にここで
- 26. 混乱オーバーロードの解決の失敗に関する数は、C#で
- 27. 未解決のオーバーロードされた関数型からのC++ラムダエラー変換
- 28. C#の解決タイプ
- 29. ジョーダ時間、時間と時間を同時に解析する
- 30. Pythonロギング:ログ時間をオーバーライド
コンパイル時にどのようにオーバーライドが解決されるか教えてください。 – ildjarn
@ildjarn:私の答えのコメントの中のリンクをチェックしたいかもしれません。 –
@Als:ダイナミック多型が完全に_disabled_(したがって質問/会話とは無関係)のコンテキストは、私が求めていたものではありません。明らかに、多型を使用するためには、多型コンテキスト内にある必要があります。 – ildjarn