C ++ MythBusters。 仮想機能の神話(アドオン)

前文



こんばんは(まあ、または誰のために)。



少し前に、C ++での仮想関数に関する記事(今はここにあります )に出くわしました。 コメントを追加できたら嬉しいですが、判明したように、ここで登録する必要があります。 実際、それが私が上記の記事にこの補足を書いた理由です。



この記事では、コンストラクター、デストラクターの仮想性の問題と、何らかの形で関数の仮想性に関連する特定の問題に取り組みたいと思います。



この記事は、中級および上級資格のプログラマを対象としています。 良い読書をしてください。



C ++の仮想コンストラクター



それでは、デザイナーから始めましょう。 ここではすべてが非常に簡単です-C ++には仮想コンストラクター(およびそれらに類似したコンストラクター)はありません。 それが起こらないのでそれだけです(具体的には、言語標準で禁止されています)。



あなたはおそらく尋ねるでしょう:「なぜあなたはこれが必要なのでしょうか?」 実際、「仮想コンストラクター」について話すのは少し間違っています。 コンストラクタは、仮想関数の意味で仮想にすることはできません。 仮想性を必要とするために、デザイナーで(および特別に設定する他の場所はありません)、作成されたオブジェクトのTBM(仮想関数のテーブル)へのポインターを構成します。



:通常、仮想性はTBMとオブジェクト内のTBMを介して実装されます。 詳細については、 こちらをご覧ください。



そのため、「仮想コンストラクタ」は、以前は未知のクラスのオブジェクトを作成するメカニズムと呼ばれることもあります。 これは、たとえば、共通の祖先から継承されたオブジェクトの配列をコピーする場合に役立ちます(この場合、必要なクラスをコピーするコンストラクターを呼び出したいのは当然です)。 C ++では、このために、通常、仮想virtual void assign (const object &o)



などの仮想関数を使用しますが、これは遍在的ではなく、他の実装も可能です。



仮想デストラクタ



しかし、逆にデストラクタは仮想的です。 そしてそれ以上-それはしばしば発見されます。

仮想関数を持つクラスで仮想デストラクタを使用するのが一般的です。 さらに、たとえば、gccは、仮想関数を宣言してデストラクタを仮想化しない場合、警告を表示します。



「子孫デストラクタの機能が親と異ならない場合、仮想デストラクタは子孫クラスの子孫に割り当てられている場合にのみ必要であり、仮想デストラクタはあまり意味がありません」という神話にしばしば遭遇します。 「今」は機能しますが、将来的には残酷な冗談を演じることができ、一般的にはあまり真実ではありません。 デストラクタが仮想ではない場合、ポインタで宣言されたタイプのデストラクタが呼び出されます。 同時に、子孫オブジェクトに対して子孫を呼び出す必要がある方が正確です。 これをルールとして受け入れるだけの価値があります。そうしないと、将来デバッグに非常に大きな問題が発生する可能性があります。プログラムがメモリの観点から流動的である理由は明らかではありません。



別の神話:純粋な仮想デストラクタはありません。 たとえそうでも。

class Sample {

public :

virtual ~Sample()=0;

};




* This source code was highlighted with Source Code Highlighter .






このクラスは抽象的であるという神話があります。 そしてこれは本当です。

また、このクラスのナルスデニックは多態性であるという一般的な誤解です。 これは正しくありません-デストラクタは継承されません。

このクラスの相続人を作成できないという神話があります。 次の例をご覧ください。

class Sample {

public :

virtual ~Sample()=0{} // , , MS VC

};



class DSample: public Sample {



};




* This source code was highlighted with Source Code Highlighter .








正常なコンパイラの場合、Sampleクラスは次のように記述する必要があります。

class Sample {

public :

virtual ~Sample()=0;

};



Sample::~Sample() {

}



* This source code was highlighted with Source Code Highlighter .






すぐにコンパイラの正常性についてのコメント、そして同時に神話:標準によって純粋な仮想を定義する。 クラス定義内の関数は許可されていません。 しかし、特定の企業は、「標準を改善する機会があれば、考えずにそれを行う」と言っています。



特定の「ボディ」ニラズを持つ純粋な仮想デストラクタを見たことがありませんか? そのため、それらが存在しないという神話も間違っています。 他の純粋な仮想関数を定義することもできます。



なぜデストラクタの定義で書く必要があるのですか? 答えは本当に簡単です:〜Sampleデストラクタは、その〜DSampleデストラクタ内のDSample de nalsdencerから呼び出されるため、決定する必要があります。そうしないと、コンパイルもされません。



純粋な仮想デストラクタとは何ですか? これは、純粋な仮想関数を作成せずにクラスを抽象化するために使用されます。 別のアプリケーションが見つかりませんでした。



メンバーデバイスポインティングノート



この部分は仮想性とは関係ないと思われます。 あなたがそう思うなら、あなたは非常に間違っています。 一般的に、C ++のメンバー関数へのポインターはあまり使用されません。 これは、一部には実装がコンパイラプログラマにとって完全な悪夢に変換されるため、言語標準のあいまいな(私には思える)章が原因です。 標準に従ってこれらの「モノ」を完全に処理できる単一のコンパイラーは知りません。



これが内部でどのように機能するかを本当に知りたい場合(同時に脳を壊す)、 www.rsdn.ru / article / cpp / fastdelegate.xmlに連絡することをお勧めします。 私はあなたに警告しなかったと言ってはいけません。



おわりに



おそらく、私があなたに伝えたいことはこれだけでしょう。 もちろん、仮想性に関連する問題のいくつかはまだ発見が必要です。私はあなたの良心に任せます8)



プログラミングで頑張ってください。



PSブログをCPPに転送する必要があります...私はそこにもっと需要があると思います。



All Articles