C++の動的バインドと静的バインド


前提:ポインタまたは参照によって虚関数が呼び出された場合にのみ、実行時に呼び出しが解析され、この場合のオブジェクトのダイナミックタイプが静的タイプと異なる可能性があります.
参照またはポインタの静的タイプと動的タイプは、C++言語が多態性をサポートする根本的なものです.(多態性は1つのインタフェース、複数の方法に簡単にまとめることができる.サブクラスのインスタンスにベースクラスの変数を直接与えることができ、その後、この変数を通じてサブクラスの方法を直接呼び出すことができる.多態はインタフェースの再利用を実現するためである.インタフェースは最も時間のかかるソースであり、実質的に1つのインタフェースを設計するのは1つのクラスを設計するよりも効率的である.)
多態性を理解してあげます.
動物の群れが競走して、亀は亀の走り方があって、ウサギはウサギの走り方があります.私たちはAnimalクラスを書きます.それは虚の方法があります.RabbitクラスはAnimalから継承され,Runメソッドを書き換え,ウサギの走り方として実現した.TortoiseクラスもAnimalから継承し,Runメソッドを書き換え,カメの走り方として実現した.Animal配列にRabbitとTortoiseオブジェクトをたくさん入れることができます(Animalから受け継がれた他のタイプでもあります).そしてforeach呼び出しの中のすべてのオブジェクトのRunメソッドを直接呼び出し、ウサギであろうとカメであろうと何であろうと、ドア自体が実際のタイプに応じて対応するRunバージョンを呼び出します.動物競走も実現します.
c++の多態性をサポートするために,動的バインドと静的バインドを用いた.彼らの違いを理解することは、マルチステート性をよりよく理解し、プログラミング中にエラーを避けるのに役立ちます.4つの名詞:1、オブジェクトの静的タイプ:オブジェクトが宣言するときに採用されるタイプを理解する必要があります.コンパイル期間中に決定されました.2、オブジェクトのダイナミックタイプ:現在指すオブジェクトのタイプ.運行期間で決められています.
オブジェクトのダイナミックタイプは変更できますが、静的タイプは変更できません.オブジェクトの静的タイプと動的タイプについては、次の例を参照してください.
class B
{
}
class C : public B
{
}
class D : public B
{
}
D* pD = new D();//pD            D*,      D*
B* pB = pD;//pB            B*,     pB      pD   D*
C* pC = new C();
pB = pC;//pB           ,         C*

3、静的バインド:バインドされているのはオブジェクトの静的タイプであり、ある特性(例えば関数)はオブジェクトの静的タイプに依存し、コンパイル期間に発生する.
4、ダイナミックバインド:バインドされているのはオブジェクトのダイナミックタイプで、ある特性(例えば関数)はオブジェクトのダイナミックタイプに依存し、実行期間に発生します.
class B
{
    void DoSomething();
    virtual void vfun();
}
class C : public B
{
    void DoSomething();//      ,            no-virtual  ,         ,       ;                      。
    virtual void vfun();
}
class D : public B
{
    void DoSomething();
    virtual void vfun();
}
D* pD = new D();
B* pB = pD;

pD->DoSomething()とpB->DoSomething()は同じ関数を呼び出しますか?
いいえ、pDとpBは同じオブジェクトを指していますが.関数DoSomethingは、静的にバインドされたno-virtual関数であるため、コンパイラはコンパイル時にオブジェクトの静的タイプに応じて関数を選択します.pDの静的タイプはD*であり、コンパイラはpD->DoSomething()を処理するときにD::DoSomething()を指します.同様に、pBの静的タイプはB*であり、pB->DoSomething()がB::DoSomething()を呼び出す.
 
pD->vfun()とpB->vfun()は同じ関数を呼び出しますか?
はい.vfunは虚関数であり、動的にバインドされているため、すなわちオブジェクトの動的タイプがバインドされている.pBとpDは静的タイプは異なるが、同時にオブジェクトを指している.彼らの動的タイプは同じで、D*であるため、彼らの呼び出しは同じ関数である:D::vfun()である.
 
上記はいずれもオブジェクトポインタの場合であり,参照(reference)の場合にも同様に適用される.
 
ポインタと参照のダイナミックタイプと静的タイプは一致しない場合がありますが、オブジェクトのダイナミックタイプと静的タイプは一致します.
D D;
D.DoSomething()とD.vfun()は、常にD::DoSomething()とD::vfun()を呼び出します.
 
動的バインドと静的バインドについては、非常に良い文章がまとめられています.
私は一言をまとめました.
虚関数のみが動的バインドを使用し、その他はすべて静的バインドです.今のところ私はまだこの言葉が適用されないことを発見していません.もし間違いがあれば、指摘してほしいです.
 
特に注意すべき点:
デフォルトのパラメータが虚関数とともに現れると、状況は少し複雑で、エラーが発生しやすい.虚関数は動的にバインドされることを知っているが,効率を実行するためにデフォルトパラメータは静的にバインドされる.
class B
{
 virtual void vfun(int i = 10);
}
class D : public B
{
 virtual void vfun(int i = 20);
}
D* pD = new D();
B* pB = pD;
pD->vfun();
pB->vfun();

pD->vfun()とpB->vfun()呼び出しは関数D::vfun()ですが、デフォルトのパラメータはいくらですか?
解析すると、デフォルトパラメータは静的バインドであり、pD->vfun()の場合、pDの静的タイプはD*であるため、デフォルトパラメータは20であるべきである.同様に、pB->vfun()のデフォルトパラメータは10であるべきである.コードを作成して検証しました.正しいです.
この特性については、誰も好きではないと思います.だから、いつまでも覚えておいてください.
「継承されたデフォルトパラメータを再定義しない(Never redefine function’s inherited default parameters value.)」