純粋な仮想関数が0で初期化されるのはなぜですか?


147

常に純粋仮想関数を次のように宣言します。

virtual void fun () = 0 ;

つまり、常に0に割り当てられます。

私が理解しているのは、これがこの関数のvtableエントリをNULLに初期化することであり、ここに他の値があるとコンパイル時エラーが発生することです。この理解は正しいですか。


12
vtableは言語要件ではなく、仮想メソッドの実装オプションにすぎないことに注意してください。コンパイラは(vtableのなし、あり、そして任意の要素なしでそこにいる0)異なる実装と同じ抽象化を作成することができます
dribeas -デビッド・ロドリゲス

@hype補足的な質問です-それが私の答え(および他のいくつか)が言うことです。

ちょうど好奇心が強い、私が与えるとどうなるか virtual void func() = 100;
krithikaGopalakrisnan

回答:


161

その理由=0は、Bjarne Stroustrupが、機能の実装時にC ++コミュニティを「純粋に」過ぎるなど、別のキーワードを取得できるとは考えていなかったためです。これについては、彼の著書、The Design&Evolution of C ++のセクション13.2.3で説明されています。

好奇心の強い= 0構文が選択されたのは、その時点で新しいキーワードが受け入れられる可能性がないためです。

彼はまた、これはvtableエントリをNULLに設定する必要はなく、そうすることは純粋な仮想関数を実装する最良の方法ではないと明言しています。


4
うん、それは単なる構文です。#define PURE = 0の多くのプロジェクトを見てきましたが、virtual void Foo()PUREと表示されます。
i_am_jorf 2010年

79
これらのプロジェクトから私を遠ざけてください:-)

27
これは#define BEGIN {#define END} ;-)よりもはるかに悪く、私は時々それを見ました。
Toon Krijthe

5
この種の気の利いたことは、C ++はあまり洗練されていないと思います。それがあまりにも多く使用されていることを考えると、それは奇妙です。日が経つにつれて言語が良くなることを願っています。
jokoon

19
つまり、言い換えれば、Bjarneは「期限に直面して」おり、「ハックを使用して」「設計上の欠陥」を乗り越えました;)(ちょうど面倒なことです)
Carl

78

C ++の設計に関するほとんどの「なぜ」の質問と同様に、最初に調べる場所は、Bjarne Stroustrup 1によるThe Design and Evolution of C ++です

奇妙な=0構文は、新しいキーワードを導入する明白な代替案よりも、pureまたは abstractその時点で新しいキーワードが受け入れられる可能性がないために選択されました。私が提案したpureとしたら、リリース2.0は抽象クラスなしで出荷されたでしょう。より優れた構文と抽象クラスのどちらかを選択できることから、私は抽象クラスを選択しました。遅延の危険を冒して、特定の争いを招くのではなく、 pure0を使用して「存在しない」ことを表すという伝統的なCおよびC ++の規則を使用しました。=0関数本体は関数ポインタのベクトルとして実装されている仮想関数の集合の(単純化したが、通常は十分な)観点でも、機能の初期化子であることを私の見解で構文フィット。[...]

1 §13.2.3構文


29

C ++標準のセクション9.2は、クラスメンバーの構文を示しています。これには次のプロダクションが含まれます。

pure-specifier:
    = 0

値について特別なことは何もありません。「= 0」は、「この関数は純粋に仮想である」という構文です。初期化、nullポインター、または数値ゼロとは関係ありませんが、それらの類似性にはニーモニック値がある場合があります。


5
C ++標準を参照する場合は+1。これは、可能な限り最良の回答の1つであり、これまでに1票しか得られなかったことは、一種の驚きです。C ++の質問を解決するには、標準を読むことが最初のステップになるはずです。
mloskot

7
@mloskot:多分それはOPの質問に答えないので、単に状況を言い換えますか?
2010

6
@just somebody-純粋な仮想関数宣言の構文は= 0何か、その構文は純粋な指定子を使用することを示す標準の引用が含まれています。他に何が知りたいですか?これは、関数本体が{}でラップされている理由を尋ねるのと同じです。答えはC ++構文で定義されているためです。
mloskot

19

この背後に何か意味があるかどうかはわかりません。言語の構文にすぎません。


16

新しい予約語は識別子にこれらの語を使用する古いプログラムを破壊するため、C ++は常に新しいキーワードの導入を避けてきました。古いコードを可能な限り尊重することは、言語の強みの1つと見なされることがよくあります。

= 0それはへのvtableのエントリを設定することに似ているので、構文は実際に選択されている場合があります0が、これは純粋に象徴的です。(ほとんどのコンパイラーは、そのようなvtableエントリーをスタブに割り当て、プログラムを中止する前にエラーを発生させます。)構文は主に選択されました。


3
新しいキーワードを導入することの欠点を説明するための+1。これは理論的根拠を理解するのに役立ちますが、C ++構文は私にはばかげて複雑に思えるので、もっと人間が読めるようにしておけばよかったと思いpureます。とにかく、その根拠を理解するのは良いことです。
キース・ピンソン、

@KeithPinson純粋なキーワードが必要な場合は、できます#define pure = 0
jdh8 2016年

@ jdh8:うーん。ただ...うーん。
sbi 2016年

付記として、Bjarneのクラスでは、「純粋な」キーワードをC ++に組み込みたいと彼は言ったが、C ++コンパイラが出荷される前のサイクルの非常に遅い段階で取得しようとした(IIRC 2週間未満)。表向きは、それはそれをしなかった。
ThePhD

@ThePhD:ISTR彼はD&Eのどこかでこれも言っています。(しかし、私はそれを調べるのが面倒です。)
sbi

11

C ++には、純粋な仮想関数を通常の仮想関数の宣言と区別する方法が必要です。彼らは= 0構文を使用することを選択しました。純粋なキーワードを追加するだけで、簡単に同じことができます。しかし、C ++は新しいキーワードを追加するのがかなり嫌で、機能を導入するために他のメカニズムを使用することを好みます。


2
-0:;自分で言うことは相当な何もないときには、大規模な引用符(+1ためのジェリー棺の回答を参照)を使用
ちょうど誰かの

7

この場合、「初期化」または「割り当て」ゼロはありません。and トークンで= 0構成される構文構造だけで、初期化も割り当てもまったく関係ありません。=0

「vtable」の実際の値とは関係ありません。C ++言語には、「vtable」などの概念はありません。さまざまな「vtable」は、特定の実装の詳細にすぎません。


3

おかしな構文の正当化は、同じことを行う別のキーワードを導入するよりも(標準の受け入れの点で)簡単だったということを読んだことを覚えています。

これは、Bjarne StroustrupによるC ++の設計と進化で言及されたと思います。


2

これはC ++文法のほんの一部だと思います。コンパイラが特定のバイナリ形式に対してこれを実際に実装する方法に制限はないと思います。おそらく、初日のC ++コンパイラにはおそらく正しいと思います。


2

= 0純粋な仮想関数を宣言します

理解されていることは、これはこの関数のvtableエントリをNULLに初期化することであり、ここに他の値があるとコンパイル時エラーが発生することです。

それは本当ではないと思います。これは特別な構文です。vtableは実装定義です。純粋なメンバーのvtableエントリは、構築時に実際にゼロにする必要があると誰も言っていません(ほとんどのコンパイラは同様のvtableを処理します)。


4
実際にはそうではありません。純粋な仮想関数の定義を提供することに問題はありません。唯一のこと= 0は、クラス全体を抽象化し、純粋な関数への仮想呼び出しを禁止することです。非仮想呼び出しは依然として完全にOKです。つまり、定義(指定した場合)が使用されます。
AnT

ゴッドボルトの出力を見てください。あいまいさや推測の余地はありません。私は後で自分自身を見ていきます
ルイス・ケルシー

のエントリ置き換えるようだ__cxa_pure_virtual arobenko.gitbooks.io/bare_metal_cpp/content/compiler_output/...代わりにベースのを:: F()
ルイスケルシー

1

まあ、実際の関数を指すようにvtableエントリを初期化することもできます。」

 virtual void fun()
 {
     //dostuff()
 }

vtableエントリはどこにも(0)を指さないように定義することも、関数を指すようにも定義できることが直観的に思えます。独自の値を指定すると、関数ではなくガベージを指すようになります。しかし、これが「= 0」が許可され、「= 1」が許可されない理由です。ニールバターワースが「= 0」を使用する理由は正しいと思う


1
私も同じような意見でしたが、多くの人が標準とBjarneのコメントを引用しているため、議論の可能性は最小限です:)
mukeshkumar
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.