En C++ 98, le pointeur nul était représenté par le littéral 0
(ou en fait toute expression constante dont la valeur était nulle). En C++ 11, nous préférons nullptr
à la place. Mais cela ne fonctionne pas pour les fonctions virtuelles pures:
struct X
{
virtual void foo() = nullptr;
};
Pourquoi ça ne marche pas? Cela n'aurait-il pas un sens total? Est-ce simplement un oubli? Sera-ce réparé?
Parce que la syntaxe dit 0
, pas l'expression ou une autre correspondance non terminale nullptr
.
Pour tout le temps seulement 0
a travaillé. Même 0L
serait mal formé car il ne correspond pas à la syntaxe.
Modifier
Clang permet = 0x0
, = 0b0
et = 00
(31.12.2013). C'est incorrect et devrait être corrigé dans le compilateur, bien sûr.
Le = 0
la notation pour les fonctions virtual
n'était pas littéralement "assign null" mais plutôt une notation spéciale qui est en fait trompeuse: une fonction virtuelle pure peut également être implémentée.
Avec divers mots clés contextuels, il serait plus logique d'autoriser abstract
plutôt que = nullptr
et avoir abstract
un mot-clé de contexte.
C'est ainsi que la grammaire est définie, si nous regardons la section projet de norme C++9.2
Membres de la classe la grammaire pertinente est la suivante:
[...]
member-declarator:
declarator virt-specifier-seqopt pure-specifieropt
[...]
pure-specifier:
= 0
^^^
La grammaire indique spécifiquement qu'un pur-spécificateur est = 0
et non une expression littérale entière ou expression , qui ne semble pas pour laisser toute marge de manœuvre. Si j'essaye des choses comme:
virtual void foo() = 0L;
ou:
virtual void foo() = NULL ;
gcc
me dit:
erreur: spécificateur pur non valide (seul '= 0' est autorisé) avant ';' jeton
et clang
dit:
erreur: l'initialisation de la fonction ne ressemble pas à un pur-spécificateur
Bien que ce qui suit fonctionne dans les deux:
#define bar 0
//...
virtual void foo() = bar;
Il semble également que clang
autorise le littéral octal , le littéral hexadécmique et littéral binaire zéro qui est un comportement incorrect.
Mettre à jour
Apparemment Visual Studio
accepte NULL
et tout littéral entier nul , y compris 0L
, 0x0
, 00
etc ... Bien qu'il n'accepte pas nullptr
.
= 0
a là une signification fixe. Ce n'est pas vraiment un zéro entier. Par conséquent, vous ne pouvez pas simplement le remplacer comme ça.
Le = 0
la syntaxe n'a pas été utilisée pour initialiser un pointeur, c'était simplement pour indiquer syntaxiquement que le virtual
fourni était pur.
D'où le = 0
la syntaxe pour déclarer pur virtual
s est inchangée.
Le point entier de nullptr
(ou la plupart du point de toute façon) est qu'il ne peut être affecté (ou utilisé pour initialiser) que des pointeurs.
Dans ce cas, vous n'initialisez pas ou n'affectez pas à un pointeur, il n'est donc même pas logique que vous puissiez l'utiliser dans cette situation.
Cela ne signifie pas qu'il s'agit d'un pointeur ou qu'il doit être égal à nullptr
.
= 0
est suffisant et signifie que la fonction virtuelle doit être pure.
La grammaire C++ 11 ne permet que 0
ici (et cela ne signifie pas un pointeur). Comme nullptr
n'est pas 0
, il échoue. NULL
ne fonctionne que lorsque NULL
est défini comme étant 0
(parfois c'est le cas, mais pas toujours). Utilisez simplement 0
ici, ou utilisez la définition suivante (si vous voulez vraiment utiliser un null, quand ce n'est pas un pointeur).
#define VIRTUAL_NULL 0
struct X
{
virtual void foo() = VIRTUAL_NULL;
};