常に純粋仮想関数を次のように宣言します。
virtual void fun () = 0 ;
つまり、常に0に割り当てられます。
私が理解しているのは、これがこの関数のvtableエントリをNULLに初期化することであり、ここに他の値があるとコンパイル時エラーが発生することです。この理解は正しいですか。
virtual void func() = 100;
常に純粋仮想関数を次のように宣言します。
virtual void fun () = 0 ;
つまり、常に0に割り当てられます。
私が理解しているのは、これがこの関数のvtableエントリをNULLに初期化することであり、ここに他の値があるとコンパイル時エラーが発生することです。この理解は正しいですか。
virtual void func() = 100;
回答:
その理由=0
は、Bjarne Stroustrupが、機能の実装時にC ++コミュニティを「純粋に」過ぎるなど、別のキーワードを取得できるとは考えていなかったためです。これについては、彼の著書、The Design&Evolution of C ++のセクション13.2.3で説明されています。
好奇心の強い= 0構文が選択されたのは、その時点で新しいキーワードが受け入れられる可能性がないためです。
彼はまた、これはvtableエントリをNULLに設定する必要はなく、そうすることは純粋な仮想関数を実装する最良の方法ではないと明言しています。
C ++の設計に関するほとんどの「なぜ」の質問と同様に、最初に調べる場所は、Bjarne Stroustrup 1によるThe Design and Evolution of C ++です。
奇妙な
=0
構文は、新しいキーワードを導入する明白な代替案よりも、pure
またはabstract
その時点で新しいキーワードが受け入れられる可能性がないために選択されました。私が提案したpure
としたら、リリース2.0は抽象クラスなしで出荷されたでしょう。より優れた構文と抽象クラスのどちらかを選択できることから、私は抽象クラスを選択しました。遅延の危険を冒して、特定の争いを招くのではなく、pure
0を使用して「存在しない」ことを表すという伝統的なCおよびC ++の規則を使用しました。=0
関数本体は関数ポインタのベクトルとして実装されている仮想関数の集合の(単純化したが、通常は十分な)観点でも、機能の初期化子であることを私の見解で構文フィット。[...]
1 §13.2.3構文
C ++標準のセクション9.2は、クラスメンバーの構文を示しています。これには次のプロダクションが含まれます。
pure-specifier:
= 0
値について特別なことは何もありません。「= 0」は、「この関数は純粋に仮想である」という構文です。初期化、nullポインター、または数値ゼロとは関係ありませんが、それらの類似性にはニーモニック値がある場合があります。
= 0
何か、その構文は純粋な指定子を使用することを示す標準の引用が含まれています。他に何が知りたいですか?これは、関数本体が{}でラップされている理由を尋ねるのと同じです。答えはC ++構文で定義されているためです。
新しい予約語は識別子にこれらの語を使用する古いプログラムを破壊するため、C ++は常に新しいキーワードの導入を避けてきました。古いコードを可能な限り尊重することは、言語の強みの1つと見なされることがよくあります。
= 0
それはへのvtableのエントリを設定することに似ているので、構文は実際に選択されている場合があります0
が、これは純粋に象徴的です。(ほとんどのコンパイラーは、そのようなvtableエントリーをスタブに割り当て、プログラムを中止する前にエラーを発生させます。)構文は主に選択されました。
pure
ます。とにかく、その根拠を理解するのは良いことです。
#define pure = 0
。
は= 0
、純粋な仮想関数を宣言します。
理解されていることは、これはこの関数のvtableエントリをNULLに初期化することであり、ここに他の値があるとコンパイル時エラーが発生することです。
それは本当ではないと思います。これは特別な構文です。vtableは実装定義です。純粋なメンバーのvtableエントリは、構築時に実際にゼロにする必要があると誰も言っていません(ほとんどのコンパイラは同様のvtableを処理します)。
= 0
は、クラス全体を抽象化し、純粋な関数への仮想呼び出しを禁止することです。非仮想呼び出しは依然として完全にOKです。つまり、定義(指定した場合)が使用されます。
__cxa_pure_virtual
arobenko.gitbooks.io/bare_metal_cpp/content/compiler_output/...代わりにベースのを:: F()
まあ、実際の関数を指すようにvtableエントリを初期化することもできます。」
virtual void fun()
{
//dostuff()
}
vtableエントリはどこにも(0)を指さないように定義することも、関数を指すようにも定義できることが直観的に思えます。独自の値を指定すると、関数ではなくガベージを指すようになります。しかし、これが「= 0」が許可され、「= 1」が許可されない理由です。ニールバターワースが「= 0」を使用する理由は正しいと思う