BruceEckelによるThinkinginC++を読んでいます。第15章(第1巻)の「コンストラクター内の仮想関数の動作」という見出しの下で、彼は次のように述べています。
コンストラクター内にいて、仮想関数を呼び出すとどうなりますか?通常のメンバー関数の内部では、何が起こるかを想像できます。オブジェクトは、メンバー関数が属するクラスに属しているのか、それから派生したクラスに属しているのかをオブジェクトが認識できないため、実行時に仮想呼び出しが解決されます。一貫性を保つために、これがコンストラクター内で行われるべきことだと思うかもしれません。
ここでブルースは、オブジェクトのコンストラクター内で仮想関数を呼び出すと、ポリモーフィズムは表示されない、つまり現在のクラスの関数が呼び出されるだけで、その関数の他の派生クラスバージョンではないことを説明しようとしています。これは有効であり、理解できます。クラスのコンストラクターは、クラスが実行されているのか、他の派生オブジェクトの作成のために実行されているのかを事前に知らないからです。さらに、そうすると、部分的に作成されたオブジェクトで関数が呼び出されることになり、悲惨なことになります。
彼が通常のメンバー関数について述べている最初の文のために私の混乱が突然起こりましたが、彼は仮想呼び出しが実行時に解決されると言っています。しかし、待ってください。クラスのメンバー関数内で、別の関数(仮想または非仮想)を呼び出すと、それ自体のクラスバージョンのみが呼び出されます。例えば
class A
{
virtual void add() { subadd(); }
virtual subadd() { std::cout << "A::subadd()\n"; }
};
class B : public A
{
void add() { subadd(); }
void subadd() { std::cout << "B::subadd()\n"; }
};
上記のコードでは、A::add()
への呼び出しsubadd()
が行われると、常に呼び出しが行われ、A::subadd()
同じことが当てはまりますB
よね?では、「仮想呼び出しは、メンバー関数が属するクラスに属しているのか、それから派生したクラスに属しているのかをオブジェクトが認識できないため、実行時に解決される」とはどういう意味ですか?
彼は基本クラスポインタを介した呼び出しに関してそれを説明していますか?(私は本当にそう思う)その場合、彼は「通常のメンバー関数の内部」と書くべきではない。これまでの私の理解では、同じクラスの別のメンバー関数内からのメンバー関数の呼び出しはポリモーフィックではありません。間違っている場合は修正してください。