C++ 98では、nullポインターはリテラル0
(または実際には値がゼロであった定数式)で表されていました。 C++ 11では、代わりにnullptr
を使用します。ただし、これは純粋な仮想関数では機能しません。
struct X
{
virtual void foo() = nullptr;
};
なぜこれが機能しないのですか?それは全く意味がありませんか?これは単に見落としですか?修正されますか?
構文は0
を示しているため、expressionやその他の非ターミナルマッチングnullptr
ではありません。
常に0
のみが機能しました。 0L
でも、構文と一致しないため、形式が正しくありません。
編集
Clangでは= 0x0
、= 0b0
、= 00
を使用できます(2013年12月31日)。これは誤りであり、もちろんコンパイラで修正する必要があります。
virtual
関数の= 0
表記は、文字通り「nullを割り当てる」のではなく、実際には紛らわしい特別な表記でした。純粋な仮想関数も実装できます。
さまざまなコンテキストキーワードを使用すると、= nullptr
ではなくabstract
を許可し、abstract
をコンテキストキーワードにすることの方が理にかなっています。
ドラフトC++標準 セクション_9.2
_ クラスメンバーを見ると、これは文法の定義方法と同じです。関連する文法は次のとおりです。
_[...]
member-declarator:
declarator virt-specifier-seqopt pure-specifieropt
[...]
pure-specifier:
= 0
^^^
_
文法は、pure-specifierが_= 0
_であり、integer literalまたはexpressionではないことを明確に示しています。小刻みな部屋。私が次のようなことを試みると:
_virtual void foo() = 0L;
_
または:
_virtual void foo() = NULL ;
_
gcc
は私に言います:
エラー: ';'の前に無効な純粋な指定子( '= 0'のみが許可されています)トークン
clang
さんのコメント:
エラー:関数の初期化子が純粋な指定子のように見えません
以下は両方で機能しますが:
_#define bar 0
//...
virtual void foo() = bar;
_
また、clang
は8進数リテラル、16進数リテラルおよびバイナリリテラルゼロを許可しているようで、これは正しくない動作です。
更新
どうやら_Visual Studio
_はNULL
と任意のゼロ整数リテラルを受け入れます_0L
_、_0x0
_、_00
_などを含みます... nullptr
を受け入れない。
= 0
には固定の意味があります。実際には整数のゼロではありません。したがって、単純にそのように置き換えることはできません。
= 0
構文は、ポインターを初期化するために使用されませんでした。これは、提供されたvirtual
が純粋であることを構文的に示すためだけでした。
従って = 0
純粋なvirtual
sを宣言するための構文は変更されていません。
nullptr
の全体のポイント(またはとにかくほとんどのポイント)は、ポインターにのみ割り当てる(または初期化に使用する)ことができます。
この場合、ポインターを初期化したり、ポインターに割り当てたりしていないので、この状況でそれを使用できることは意味がありません。
これは、それがポインタであることや、nullptr
と等しくなければならないことを意味するものではありません。
= 0
は十分であり、仮想関数が純粋であることを意味します。
C++ 11の文法では、ここでは0
のみを許可しています(これはポインターを意味するものではありません)。 nullptr
は0
ではないため、失敗します。 NULL
は、NULL
が0
として定義されている場合にのみ機能します(場合によってはそうですが、常にそうとは限りません)。ここで0
を使用するか、次の定義を使用します(本当にnullを使用したい場合は、ポインターでない場合)。
#define VIRTUAL_NULL 0
struct X
{
virtual void foo() = VIRTUAL_NULL;
};