C ++ 11では、プログラマーが複雑な継承構造型を記述できるように、仮想関数記述子のオーバーライドが導入されました。仮想関数が宣言されるときに派生クラスがオーバーライド記述子を使用する場合、関数は基本クラスをオーバーロードする必要があります同じ名前の関数。それ以外の場合、コードはコンパイルされません。リスト2-25で示されるこの簡単な例を見てみましょう。
リスト2-25
struct Base {
virtual void Turing()= 0;
virtual void Dijkstra()= 0;
virtual void VNeumann(int g)= 0;
virtual void DKnuth()const;
void Print();
};
struct DerivedMid :public Base {
// void VNeumann(double g);
//インターフェースは分離されているので、VNeumann関数のもう1つのバージョンが必要でした
};
struct DerivedTop:public DerivedMid {
void Turing()override;
void Dikjstra()override; //コンパイルを渡すことができない、スペルが間違っている、オーバーロードされていない
void VNeumann(double g)オーバーライド; //コンパイルを渡すことができない、パラメータが一貫していない、オーバーロードされていない
void DKnuth()オーバーライド; //コンパイルを渡せない、一貫性がなく、オーバーロードされない
void Print()override; //コンパイルできない、非仮想関数のオーバーロード
};
//コンパイルオプション:g ++ -c -std = c ++ 11 2-10-3.cpp
コードリスト2-25では、基本クラスBaseでは、いくつかの仮想関数(インターフェース)と非仮想関数Printが定義されています。その派生クラスDerivedMidでは、基本クラスのBaseインターフェースはオーバーロードされませんが、DerivedMidの作成者がかつて「void VNeumann(double g)」バージョンをオーバーロードしたいと思ったことをコメントで見つけることができます。このコメント行は、明らかにDerivedTopを作成したプログラマーを混乱させます。そのため、DerivedTopの作者は、Baseクラスのすべてのインターフェースをオーバーロードするときに3つの異なる間違いを犯しました:
スペルミスの関数名、およびDijkstraが誤ってDikjstraを作成しました。
関数プロトタイプが一致せず、VNeumann関数のパラメーター型がdouble型と誤っており、DKnuthの定数性が派生クラスでキャンセルされています。
非仮想関数の印刷を書き直しました。
コードリスト2-25のオーバーライド修飾子がない場合、DerivedTop作成者の4か所は過去にコンパイルできますが、彼の意欲からの大きな逸脱があります(仮想関数をオーバーロードしたい)が、コンパイラーはエラーを報告せず、コンパイルを続行します。トラブルシューティングが難しい。キーワードoverrideを追加して、コンパイラーが正しくオーバーロードされているかどうかをコンパイラーがチェックできるようにします。オーバーライド修飾子DerivedTopがない場合、作成者はコンパイル後に多くのエラーが発生したことに気付かない可能性があります。コンパイラは、上記の3つのエラーについて警告を発しないためです。ここでオーバーライド修飾子を使用すると、コンパイラーが補助的なチェックを確実に実行できます。リスト2-25のコードでは、DerivedTop作成者の4つのエラーがコンパイルに失敗したことがわかります。
さらに、C ++では、派生クラスのライターが新しいインターフェイスが作成されたと考えた場合、実際には低レベルのインターフェイスがオーバーロードされます(get、set、printなどの単純な名前は簡単です)このような状況)、コンパイラはまだこの状況では役に立ちません。ただし、派生クラス変数のインターフェイスがこのインターフェイスを呼び出す場合、仮想関数のオーバーヘッドの可能性に加えて、派生クラスのバージョンが引き続き実行されるため、このような意図的ではないオーバーロードは通常、大きな問題を引き起こしません。したがって、コンパイラーが「再ロードされていない」状況のチェックを提供する必要はありません。「オーバーライド」オーバーライドキーワードをチェックすることは、プログラマにとってより意味があります。
また、第1章で説明したように、final / overrideは通常の変数名としても定義でき、関数の後に出現する場合にのみ継承/派生を制御できます。この設計では、最終的な/オーバーライド変数または関数名を含む多くのC ++ 98コードをC ++コンパイラでコンパイルできます。ただし、セキュリティ上の理由から、不要なエラーを防ぐために、C ++ 11コードでは、このような変数名をできるだけ避けるか、マクロでそれらを定義することをお勧めします。
提案:派生クラスがオーバーロードされた仮想関数のような場合は、キーワードオーバーライドを追加して、コンパイラーがそれが正しくオーバーロードされているかどうかを確認できるようにします。このキーワードが追加されていない場合、重大なエラーはありませんが、コンパイラーチェックの安全性は低くなります。
// test_max.cpp:定型制御制御台の使用手順の入口点。
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
int main(void)
{
string strArr1 [] = {"Cjc"、 "is"、 "a"};
string * pStrArr1 = new string [2];
pStrArr1 [0] = "良い";
pStrArr1 [1] = "男の子。";
cout << "string型の長さは" << sizeof(string)<< endl;
for(int i = 0; i <sizeof(strArr1)/ sizeof(string); i ++)
{
cout << strArr1 [i];
}
for(int i = 0; i <sizeof(pStrArr1)/ sizeof(string); i ++)
{
cout << pStrArr1 [i];
}
system( "pause");
上記の結果は次のとおりです。VS2010windows7 32ビットオペレーティングシステムでは、文字列クラスの長さは32バイトです(文字列の実現に関連
)。sizeofは動的に割り当てられたメモリブロックサイズを見つけることができないため、sizeof(pStrArr1)の結果は4