C ++とDelphiの関数オーバーライドと過負荷
Spacesoft【暗い夜の砂】
オブジェクト指向プログラミングでは、サブクラスが基本クラスからの機能を継続する場合、サブクラスは、次のような基本クラスとは異なる機能の一部を扱う必要があります。
クラスチュマン
{
公共:
void saymyname()//オブジェクトの名前を印刷します
{
cout <<こんにちは、私は人間です<< endl;
}
};
そのサブクラスに同じ名前、同じパラメーターと戻り値(1つの文、同じ関数)を持つ関数Saymynameがある場合、それはどの関数を呼び出しますか?たとえば、クラスCMARKが現在あります
クラスCmark:パブリックチュマン
{
公共:
void saymyname()
{
cout <<こんにちは、私はマークです<< endl;
}
};
次に、次のプログラムセグメントを尋ねなければなりません。
Chuman *ph = new cmark;
if(ph)
ph-> saymyname();
それ以外
cout <<キャストエラー!
phを削除します。
ph = null;
こんにちは、私は印刷したいマークですか?
いいえ。こんにちは、私は人間です。それはひどいです、そして、私たちが人を指して彼に彼の名前を言うように頼むとき、彼は彼が彼の名前を言うのではなく「人」であると私たちに言います。この問題の理由は、基本クラスのポインターを使用して公開クラスを指して、基本クラスから続く派生クラスのメンバー関数にアクセスできることです。しかし、派生クラスに同じ名前の関数がある場合、結果は、派生クラス自体の関数ではなく、基本クラスの同じ名前の関数にまだアクセスしています。実際、私たちが望んでいるのは、同じ名前のこれらの関数のどれが実際のタイプのオブジェクトによって呼び出されるべきかを決定することです。つまり、そのような解像度は動的です。または、オブジェクトがサブタイプである場合、サブクラス内の同じ名前の実装が基本クラスの実装を上書きすることを言えます。
C ++のこの問題の処理から始めましょう。
これは、C ++の多型の典型的な例です。具体的には、仮想キーワードを使用して、以前の例として関数を説明する必要があります。
クラスチュマン
{
公共:
virtual void saymyname()//オブジェクトの名前を印刷します
{
cout <<こんにちは、私は人間です<< endl;
}
};
このように、他のコードはまだ同じですが、私たちのCMARKはすでにその名前を言う方法を知っています。 CmarkのSaymyname()関数が仮想キーワードを追加したかどうかは関係ありません。これは、C ++構文の規定によれば、同じ名前のChuman関数を上書きするため、仮想自体になるためです。なぜ仮想キーワードにそのような魔法の効果があるのですか? C ++ FAQ Liteはこれを次のように説明しています。C++では、「仮想メンバー関数は動的に決定されます(実行時)。つまり、メンバー関数は動的に選択され、選択はオブジェクトのタイプに基づいています。そのオブジェクトへのポインター/参照のタイプ」。したがって、私たちのpHは、それが実際に独自のタイプで宣言されたチュマンではなく、タイプのcmarkのオブジェクトを指していることを発見しているため、CmarkのSaymynameと呼ばれます。
Delphiはオーバーライドキーワードを使用して、関数のオーバーライドを説明します。上書き関数は仮想または動的でなければなりません。つまり、関数には、次のような宣言されたときにこれら2つのインジケーターのいずれかを含める必要があります。
手順抽選;
オーバーライドする必要がある場合は、サブクラスのオーバーライドインジケーターでそれを再作成するだけです。
手順の抽選;
構文的に、仮想および動的としての宣言は同等です。違いは、前者が実装の速度を最適化し、後者はコードサイズを最適化することです。
ベースクラスとサブクラスの両方に同じ関数名とパラメーターが含まれていて、オーバーライドインジケーターがサブクラスに追加されていない場合はどうなりますか?これも構文的に正しいです。これは、サブクラスの関数の関数実装が基本クラスの実装を隠すことを意味しますが、どちらも派生クラスに存在します。次に、この記事の冒頭の最初の例に示されている状況に戻りましょう。私たちが人を指して自分の名前を言うように頼むとき、彼は自分の名前を言うのではなく、「人」だと言います。名前。
Delphiでしばしば過負荷と呼ぶ過負荷関数と過負荷機能とは異なり、過負荷機能と呼ばれるものはまだ存在し、パラメーターはどの実装が呼び出されるかを決定します。もちろん、関数が削除された過負荷が基本クラスの関数パラメーターと同じである場合、上記のようにベースクラスの実装が非表示になります。オーバーライドとは、上書きされた関数を不可視で実際に上書きすることを意味し、元の実装が消えます。このため、多くの記事やいくつかの本でさえ、誤って翻訳されている本が過負荷に翻訳されていますが、これは適切ではないと思います。