純粋な仮想関数は常に次のように宣言します。
virtual void fun () = 0 ;
つまり、常に0に割り当てられます。
私が理解しているのは、これはこの関数のvtableエントリをNULLに初期化することであり、ここの他の値はコンパイル時エラーになることです。この理解は正しいですか?
理由 =0
が使用されているのは、Bjarne Stroustrupが、機能が実装された時点でC++コミュニティを超えて「純粋」などの別のキーワードを取得できるとは思わなかったことです。これは彼の本 C++の設計と進化 、セクション13.2.3で説明されています:
好奇心の強い= 0構文が選択されました...当時、新しいキーワードが受け入れられる機会がなかったからです。
彼はまた、vtableエントリをNULLに設定する必要はなく、そうすることは純粋な仮想関数を実装する最良の方法ではないことを明示的に述べています。
C++の設計に関するほとんどの「なぜ」質問と同様に、最初に見るべき場所はC++の設計と進化、Bjarne Stroustrupによる1:
好奇心
=0
構文は、新しいキーワードpure
またはabstract
を導入するという明白な代替案よりも選ばれました。なぜなら、その時点では、新しいキーワードが受け入れられる機会がなかったからです。pure
を提案した場合、リリース2.0は抽象クラスなしで出荷されていました。より良い構文と抽象クラスの選択を考えると、抽象クラスを選択しました。pure
をめぐる遅延と特定の戦いを招く代わりに、「存在しない」ことを表すために0を使用する伝統的なCおよびC++の規則を使用しました。=0
構文は、関数本体が関数の初期化子であり、関数ポインターのベクトルとして実装される仮想関数のセットの(単純ですが、通常は適切な)ビューを持つという私の見解に適合します。 [...]
1§13.2.3構文
C++標準のセクション9.2は、クラスメンバーの構文を示しています。これには次の生産が含まれます。
pure-specifier:
= 0
値について特別なことは何もありません。 「= 0」は、「この関数は純粋仮想」と言うための単なる構文です。初期化やNULLポインター、数値ゼロとは関係ありませんが、それらの類似性にはニーモニック値が含まれている場合があります。
この背後に何か意味があるかどうかはわかりません。それは言語の単なる構文です。
新しい予約語は識別子にこれらの単語を使用する古いプログラムを破壊するため、C++は常に新しいキーワードの導入を避けてきました。可能な限り古いコードを尊重することは、言語の長所の1つと見なされることがよくあります。
= 0
構文は、vtableエントリを0
に設定することに似ているため、実際に選択された可能性がありますが、これは純粋にシンボリックです。 (ほとんどのコンパイラは、そのようなvtableエントリをプログラムを中止する前にエラーを出力するスタブに割り当てます。)構文は主に選択されました。
C++には、純粋な仮想関数と通常の仮想関数の宣言を区別する方法が必要です。彼らは= 0
構文。純粋なキーワードを追加するだけで、簡単に同じことができます。しかし、C++は新しいキーワードを追加することを嫌い、他のメカニズムを使用して機能を導入することを好みます。
この場合、「初期化」または「割り当て」ゼロはありません。 = 0
は、=
および0
トークン。初期化または割り当てのいずれともまったく関係ありません。
「vtable」の実際の値とは関係ありません。 C++言語には、「vtable」などの概念はありません。さまざまな「vtable」は、特定の実装の詳細にすぎません。
面白い構文の正当化は、同じことをする別のキーワードを導入するよりも(標準化の観点から)簡単だったということを読んだことを覚えています。
これはBjarne Stroustrupによる「C++の設計と進化」で言及されたと思います。
これはC++の文法の一部にすぎないと思います。特定のバイナリ形式に対してコンパイラが実際にこれを実装する方法に制限はないと思います。おそらく、初期のC++コンパイラに適していると思われます。
= 0
は純粋な仮想関数を宣言します。
理解されていることは、これはこの関数のvtableエントリをNULLに初期化することであり、ここの他の値はコンパイル時エラーになることです
私はそれが本当だとは思わない。特別な構文です。 vtableは実装定義です。純粋なメンバーのvtableエントリは、構築時に実際にゼロにする必要があると言う人はいません(ただし、ほとんどのコンパイラはvtableを同様に処理します)。
さて、実際の関数を指すようにvtableエントリを初期化することもできます」
virtual void fun()
{
//dostuff()
}
Vtableエントリはどこにも(0)または関数を指すように定義できると直感的に思えます。独自の値を指定すると、おそらく関数ではなくガベージを指すようになります。しかし、それが「= 0」が許可され、「= 1」が許可されない理由です。ニール・バターワースは、「= 0」が使用される理由について正しいと思う