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á?
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.
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.
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
.
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í.
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.
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.
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.
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;
};
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