que pensé una solicitud explícita de instancias sería una instancia de forma automática todos los miembros de la clase base también, pero me da un linker error: unresolved external symbol "public: void Base<int>::foo(int)"
en la construcción de este código utilizando Visual Studio 2008 o 2010.Hacer instancias explícitas de plantillas de clase C++ Crear una instancia de clases base dependientes?
Tenga en cuenta que la adición de una llamada a foo()
dentro bar()
obliga al compilador instanciar Base<int>::bar()
y la compilación tiene éxito, por lo que parece que el compilador tiene toda la información necesaria para crear una instancia de foo()
.
Obviamente, instanciar explícitamente Base<int>
en source.cpp permite que la compilación tenga éxito, pero parece una tontería tener que instanciar explícitamente cualquier clase base dependiente siempre que ejemplifique explícitamente una clase derivada.
¿Es esto normal? No pude encontrar lo que dice la norma con respecto a este tema.
header.h
template<typename T>
class Base {
public:
void foo();
};
template<typename T>
class Derived : public Base<T> {
public:
void bar();
};
source.cpp
#include "header.h"
template<typename T>
void Base<T>::foo() { }
template<typename T>
void Derived<T>::bar() {
// this->foo(); // adding this forces instantiation of foo()???
}
template class Derived<int>;
main.cpp
#include "header.h"
int main() {
Derived<int> d;
d.foo(); // Linker Error: unresolved external symbol "public: void Base<int>::foo(int)"
}
Editar:
Parece que el estándar dice que solo los miembros de una clase son instanciados por una instancia de clase explícita, por lo que el error del enlazador se justifica en mi ejemplo.
Tenga en cuenta que una clase se define por class-head {member-specification} y "La especificación miembro en una definición de clase declara el conjunto completo de miembros de la clase; ningún miembro se puede agregar en otro lugar". Por lo tanto, los miembros solo se encuentran entre llaves {}, y los miembros de la clase base pública no se convierten en miembros de la clase derivada, simplemente son accesibles desde la clase derivada o por los objetos de la clase derivada.
Mi única pregunta restante es por qué el estándar especifica que la creación de instancias explícita de una plantilla de clase solo instancia los miembros y no los miembros de las clases base? Mi suposición es que esto permite un mayor control de lo que se ejemplifica explícitamente donde. Alguien que está usando instancias explícitas de clases de plantillas muy probablemente tenga las definiciones de clase base en un archivo diferente de las definiciones de clases derivadas, y instanciaría explícitamente cada una por separado.
¿Agregar un constructor explícito para la creación de instancias derivadas de la clase Base? Sospecho que el compilador está tratando de no hacer más trabajo del necesario. Tener un constructor puede hacer que se dé cuenta de que también necesita construir Base, y eso podría desencadenarlo. Además, ¿has probado gcc u otros compiladores? –
Agregar un constructor con o sin un argumento y con o sin la palabra clave "explicit" no desencadena la instanciación de la clase base foo(), pero una llamada a foo() desde la barra miembro derivada() desencadena la instanciación implícita. – JohnPS