2011-01-13 8 views
8

Tengo algunos problemas para implementar funciones virtuales puras heredadas de alguna clase abstracta, cuando las clases en cuestión se dividen en *.h y *.cpp files. El compilador (g++) me dice que la clase derivada no se puede instanciar debido a la existencia de funciones puras.Implementación pura de la función virtual de C++ y archivos de encabezado

/** interface.h**/ 
namespace ns 
{ 
    class Interface { 
     public: 
      virtual void method()=0; 
    } 
} 

/** interface.cpp**/ 
namespace ns 
{ 
    //Interface::method()() //not implemented here 
} 

/** derived.h **/ 
namespace ns 
{ 
    class Derived : public Interface { 
     //note - see below 
    } 
} 

/** derived.cpp **/ 
namespace ns 
{ 
    void Derived::Interface::method() { /*doSomething*/ } 
} 

/** main.cpp **/ 
using namespace ns; 
int main() 
{ 
    Interface* instance = new Derived; //compiler error 
} 

¿Quiere decir esto que tengo que declarar el método() dos veces - en la interfaz de *.h y en el derived.h también? ¿No hay otra forma de evitarlo?

+0

Esto no es válido C++. 'public void method() = 0;' se parece más a Java para mí. –

+0

Primero, no hay razón para tener un archivo .cpp en el que lo único es un espacio de nombres en blanco. No necesita un archivo de implementación para un encabezado que contenga una clase abstracta. – Falmarri

+0

@Falmarri es correcto. –

Respuesta

12

Has olvidado declarar Derived::method().

Intentó definirlo al menos, pero escribió Derived::Interface::method() en lugar de Derived::method(), pero ni siquiera intentó declararlo. Por lo tanto, no existe.

Por lo tanto, no tiene Derivedmethod(), por lo tanto, la función virtual pura method() de Interface no fue anulada ... y por lo tanto, también es puro Derived virtual y no puede ser instanciada.

Además, public void method()=0; no es válido C++; se parece más a Java. Las funciones de miembros virtuales puros tienen que ser realmente virtuales, pero no ha escrito virtual. Y los especificadores de acceso van seguidos de dos puntos:

public: 
    virtual void method() = 0; 
+0

El bit vacío probablemente sea un error tipográfico, tampoco es java. – time4tea

+0

@ time4tea: De hecho tampoco es Java válido, pero con los dos puntos faltantes y la implicación de que el especificador de acceso ha sido visto como algo unido a la declaración, ¡está un poco más cerca que en C++! –

+0

La sintaxis fue mi error tipográfico, vea mi comentario en el post de apertura :) lo siento. Además, el método 'Derived :: Interface ::()' es mi intento de definir una función que debe heredarse de Interface. Mi pregunta original era algo así como "¿puedo implementar (definir) una función virtual pura heredada sin declararla explícitamente en el archivo' .h' de la clase derivada? ". La razón por la que me gustaría hacer eso es para evitar saturar mi archivo de encabezado cuando la clase hereda de varias interfaces, que contienen varios virtuales puros cada ... – Neo

11

Debe declarar su método en la subclase.

// interface.hpp 
class Interface { 
public: 
    virtual void method()=0; 
} 

// derived.hpp 
class Derived : public Interface { 
public: 
    void method(); 
} 

// derived.cpp 
void 
Derived::method() 
{ 
    // do something 
} 
+0

Creo que te refieres a ** declarar ** (no definir). –

+0

@MikeSlutsky sí, lo hice. – robert

+0

@robert Gracias por la respuesta. ¿Puedes elucidar las razones de eso? Viniendo de Java parece muy sucio tener que hacer eso. Cuando tenemos muchas clases derivadas diferentes y muchos métodos en la interfaz base, necesitamos cambiar muchos archivos en caso de cambios en la interfaz base. –

Cuestiones relacionadas