Pregunta

Tengo una clase de plantilla definida como tal:

template <class T>
class Command {
public:
    virtual T HandleSuccess(std::string response) = 0;
    virtual std::string FullCommand() const = 0;
    // ... other methods here ...
};

¿C ++ me permitirá crear una subclase sin plantilla de una clase de plantilla? Lo que quiero decir es que puedo hacer algo como esto:

class NoopCommand : public Command<NoopResult> {
public:
    NoopResult HandleSuccess(std::string response);
    std::string FullCommand() const;
    // ... other methods here ...
};

Como es, eso no funciona para mí porque dice que las siguientes funciones virtuales no están definidas:

T admix::Command<T>::HandleSuccess(std::string) [with T = admix::NoopResult]
std::string admix::Command<T>::FullCommand() const [with T = admix::NoopResult]

¿Cómo puedo definirlos específicamente para la T dada?

¿Fue útil?

Solución 5

litb encontró la solución en ## c ++ anoche.

El problema fue que estaba pasando un NoopCommand a una función como esta:

void SendCommand(Command<T> command);

Cuando debería haber hecho la firma esto:

void SendCommand(Command<T>& command);

Hacer ese cambio permite que todo se compile.

Otros consejos

Como nos dimos cuenta en IRC, eso se debe a que usted

  1. Hizo que sus funciones no fueran puras
  2. Cortó la parte del objeto derivado. Así que las funciones de la clase base fueron llamadas porque el objeto ya no era un objeto derivado completo.

(A continuación aparece mi sospecha sobre las versiones anteriores de su pregunta: la mantengo para mayor consideración y para que los comentarios sean significativos)


Creo que el problema aquí es que el compilador es libre de instanciar cualquier función virtual miembro de una plantilla de clase, incluso si no se utiliza (es decir, no se llama). La creación de instancias de una función necesitará una definición de función que se proporcionará. Intente agregar esto en el encabezado, donde el compilador los encontrará y creará una definición de:

template<typename T>
T Command<T>::HandleSuccess(std::string response) { /* put some default action ... */ }

template<typename T>
std::string Command<T>::FullCommand() const { /* put some default action ... */ }

C ++ Standard 14.7.1 / 9 :

  

Una implementación no creará una instancia implícitamente de una plantilla de función, una plantilla miembro, un no virtual   Función miembro, una clase miembro o un miembro de datos estáticos de una plantilla de clase que no requiere creación de instancias. No se especifica si una implementación crea una instancia de forma implícita de una función miembro virtual de una plantilla de clase si la función de miembro virtual no sería instanciada de otro modo.   

" las funciones virtuales no están definidas " significa que no ha definido los cuerpos de función de NoopCommand :: HandleSuccess y NoopCommand :: FullCommand.

Lo siguiente debería resolver su problema.

class NoopCommand : public Command<NoopResult> {
public:
    NoopResult HandleSuccess(std::string response) {}
    std::string FullCommand() const {}
    // ... other methods here ...
};

O tienes un NoopCommand.cpp, asegúrate de que esté incluido en tu proceso de compilación.

El patrón que usas es ampliamente conocido como " Patrón de Plantilla Curiosamente Recurrente " . así que, sí, puedes hacer eso.
No puedo pensar en una razón por la que no se compila.

El código que me diste se compila sin errores (luego de agregar una estructura NoopResult {}; ). Tal vez haya un problema en el código que omitiste?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top