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