web-dev-qa-db-ja.com

C ++ 11の純粋仮想関数

C++ 98では、nullポインターはリテラル0(または実際には値がゼロであった定数式)で表されていました。 C++ 11では、代わりにnullptrを使用します。ただし、これは純粋な仮想関数では機能しません。

struct X
{
    virtual void foo() = nullptr;
};

なぜこれが機能しないのですか?それは全く意味がありませんか?これは単に見落としですか?修正されますか?

37
fredoverflow

構文は0を示しているため、expressionやその他の非ターミナルマッチングnullptrではありません。

常に0のみが機能しました。 0Lでも、構文と一致しないため、形式が正しくありません。

編集

Clangでは= 0x0= 0b0= 00を使用できます(2013年12月31日)。これは誤りであり、もちろんコンパイラで修正する必要があります。

virtual関数の= 0表記は、文字通り「nullを割り当てる」のではなく、実際には紛らわしい特別な表記でした。純粋な仮想関数も実装できます。

さまざまなコンテキストキーワードを使用すると、= nullptrではなくabstractを許可し、abstractをコンテキストキーワードにすることの方が理にかなっています。

29
Dietmar Kühl

ドラフト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;
_

また、clang8進数リテラル16進数リテラルおよびバイナリリテラルゼロを許可しているようで、これは正しくない動作です。

更新

どうやら_Visual Studio_はNULLと任意のゼロ整数リテラルを受け入れます_0L_、_0x0_、_00_などを含みます... nullptrを受け入れない。

17
Shafik Yaghmour

= 0には固定の意味があります。実際には整数のゼロではありません。したがって、単純にそのように置き換えることはできません。

10
user2345215

= 0構文は、ポインターを初期化するために使用されませんでした。これは、提供されたvirtualが純粋であることを構文的に示すためだけでした。

従って = 0純粋なvirtualsを宣言するための構文は変更されていません。

6
John Dibling

nullptrの全体のポイント(またはとにかくほとんどのポイント)は、ポインターにのみ割り当てる(または初期化に使用する)ことができます。

この場合、ポインターを初期化したり、ポインターに割り当てたりしていないので、この状況でそれを使用できることは意味がありません。

6
Jerry Coffin

これは、それがポインタであることや、nullptrと等しくなければならないことを意味するものではありません。

= 0は十分であり、仮想関数が純粋であることを意味します。

2

C++ 11の文法では、ここでは0のみを許可しています(これはポインターを意味するものではありません)。 nullptr0ではないため、失敗します。 NULLは、NULL0として定義されている場合にのみ機能します(場合によってはそうですが、常にそうとは限りません)。ここで0を使用するか、次の定義を使用します(本当にnullを使用したい場合は、ポインターでない場合)。

#define VIRTUAL_NULL 0
struct X
{
    virtual void foo() = VIRTUAL_NULL;
};
1
Konrad Borowski