Funciones virtuales puras en C++11


En C++98, el puntero nulo estaba representado por el literal 0 (o de hecho cualquier expresión constante cuyo valor era cero). En C++11, preferimos nullptr en su lugar. Pero esto no funciona para funciones virtuales puras:

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

¿por Qué esto no funciona? ¿No tendría sentido? Es simplemente un descuido? ¿Se arreglará?

Author: fredoverflow, 2013-12-31

8 answers

Porque la sintaxis dice 0, no expresión o alguna otra coincidencia no terminal nullptr.

Para todo el tiempo solo 0 ha funcionado. Incluso 0L estaría mal formado porque no coincide con la sintaxis.

Editar

Clang permite = 0x0, = 0b0 y = 00 (31.12.2013). Eso es incorrecto y debería arreglarse en el compilador, por supuesto.

 40
Author: Johannes Schaub - litb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-31 18:59:38

La notación = 0 para las funciones virtual no era literalmente "asignar null", sino una notación especial que en realidad es engañosa: también se puede implementar una función virtual pura.

Con varias palabras clave de contexto, tendría más sentido permitir abstract en lugar de = nullptr y tener abstract como palabra clave de contexto.

 28
Author: Dietmar Kühl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-31 17:54:10

Así es como se define la gramática, si nos fijamos en la sección draft C++ standard 9.2 Miembros de la clase la gramática relevante es la siguiente:

[...]
member-declarator:
 declarator virt-specifier-seqopt pure-specifieropt
[...]
pure-specifier:
  = 0
  ^^^

La gramática indica específicamente que un puro-especificador es = 0 y no un literal entero o expresión, que no parece dejar ningún margen de maniobra. Si intento cosas como:

virtual void foo() = 0L;

O:

virtual void foo() = NULL ;

gcc me dice:

Error: especificador puro no válido (solo se permite '= 0') antes de'; ' token

Y clang dice:

Error: el inicializador en la función no se parece a un especificador puro

Aunque lo siguiente funciona en ambos:

#define bar 0
//...
virtual void foo() = bar;

También parece Que clang permite octal literal, hexadecmical literal y binario literal cero, lo que es un comportamiento incorrecto.

Update

Aparentemente Visual Studio acepta NULL y cualquier cero entero literal incluyendo 0L, 0x0, 00 etc... Aunque no acepta nullptr.

 17
Author: Shafik Yaghmour,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-01 01:05:02

= 0 tiene un significado fijo allí. No es realmente un cero entero allí. Por lo tanto, no puedes simplemente reemplazarlo así.

 10
Author: user2345215,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-31 17:52:54

El punto completo de nullptr (o la mayor parte del punto de todos modos) es que solo se puede asignar a (o usar para inicializar) punteros.

En este caso, no está inicializando o asignando a un puntero, por lo que ni siquiera tiene sentido que pueda usarlo en esta situación.

 6
Author: Jerry Coffin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-31 17:56:58

La sintaxis = 0 no se usó para inicializar un puntero, sino simplemente para indicar sintácticamente que el virtual proporcionado era puro.

Por lo tanto, la sintaxis = 0 para declarar virtual s puros no cambia.

 5
Author: John Dibling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-31 17:53:17

Eso no significa que sea un puntero, o que tenga que ser igual a nullptr.

= 0 es suficiente y significa que la función virtual debe ser pura.

 2
Author: Stephane Rolland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-31 18:08:03

La gramática de C++11 solo permite 0 aquí (y no significa un puntero). Como nullptr no es 0, falla. NULL solo funciona cuando NULL se define como 0 (a veces es el caso, pero no siempre). Simplemente use 0 aquí, o use following define (si realmente desea usar un null, cuando no es un puntero).

#define VIRTUAL_NULL 0
struct X
{
    virtual void foo() = VIRTUAL_NULL;
};
 1
Author: Konrad Borowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-31 20:04:57