c++ - sirve - interfaces poo
¿Por qué gcc y clang me permiten construir una clase abstracta? (1)
¿Por qué gcc y clang me permiten construir una clase abstracta?
Porque están rotos, según la norma.
La sección 10.4 define cómo funcionan las clases abstractas. Contiene esta línea (en C ++ 14):
no se pueden crear objetos de una clase abstracta, excepto como subobjetos de una clase derivada de ella.
Las reglas de inicialización para las referencias con las listas de iniciación armadas construirán un temporal y lo vincularán a la referencia. Los temporales son objetos. Como tal, el código que escribiste anteriormente intentará crear un "objeto de una clase abstracta" como algo distinto de un "subobjeto de una clase derivada de él".
Algo que la norma prohíbe expresamente. No hay ambigüedad en la norma en este sentido. Si bien 10.4, p3 sí especifica los lugares en los que el compilador debe corregir el error si los escribe (declarando clases abstractas como parámetros de función, conversiones explícitas, etc.), el estándar aún requiere implementaciones para prohibir la construcción de una clase abstracta como algo que no sea un "subobjeto de una clase derivada de él".
Un temporal no es un "subobjeto de una clase derivada de él". Y por lo tanto, los compiladores están obligados a prohibir esto.
Cualquier compilador que no tenga un error.
El siguiente código se compila en una amplia gama de versiones de gcc y clang: cuando se compila y ejecuta con gcc 5.3.1, se imprime
UNA()
luego aborta con un error de llamada virtual puro.
#include <stdio.h>
class A
{
public:
A() {
printf("A()/n");
}
virtual void b() const = 0;
};
int main()
{
const A& a{};
a.b();
return 0;
}
Me doy cuenta de que vincular una referencia a un temporal no es lo ideal (aunque creo que este caso está cubierto por algún tipo de extensión de por vida), pero también funciona cuando se intenta llamar a un método que toma una referencia constante como:
Foo({});
Por conveniencia, aquí hay un ejemplo de compilación con clang 3.2: Compiler Explorer