web-dev-qa-db-fra.com

Fonctions virtuelles pures en C ++ 11

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é?

37
fredoverflow

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.

43

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.

29
Dietmar Kühl

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.

17
Shafik Yaghmour

= 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.

10
user2345215

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 virtuals est inchangée.

6
John Dibling

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.

6
Jerry Coffin

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.

2
Stephane Rolland

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;
};
1
Konrad Borowski