2011-01-13 22 views
8

Sto riscontrando qualche problema nell'implementazione di funzioni virtuali pure ereditate da una classe astratta, quando le classi in questione sono suddivise in *.h e *.cpp files. Il compilatore (g++) mi dice che la classe derivata non può essere istanziata a causa dell'esistenza di funzioni pure.File di intestazione e intestazione di pura funzione virtuale di C++

/** 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 
} 

Questo significa che devo dichiarare il metodo() due volte - Nell'interfaccia del *.h e nel derived.h troppo? Non c'è altro modo per aggirare?

+0

Questo non è valido C++. 'public void method() = 0;' Mi sembra più simile a Java. –

+0

Innanzitutto, non c'è motivo di avere un file .cpp in cui l'unica cosa è uno spazio dei nomi vuoto. Non è necessario un file di implementazione per un header che contiene una classe astratta. – Falmarri

+0

@Falmarri è corretto. –

risposta

12

Hai dimenticato di dichiarare Derived::method().

Hai provato a definirlo almeno, ma hai scritto Derived::Interface::method() anziché Derived::method(), ma non hai nemmeno provato a dichiararlo. Quindi non esiste.

Pertanto, Derived non ha method(), quindi la funzione virtuale pura method() da Interface non era sovrascritti ... e quindi, Derived è anche puro virtuale e non può essere istanziata.

Inoltre, public void method()=0; non è valido C++; sembra più come Java. Le funzioni dei membri virtuali puri devono effettivamente essere virtuali, ma non hai scritto virtual. E gli specificatori di accesso sono seguiti da due punti:

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

Il bit del vuoto probabilmente è un refuso, non è neanche java. – time4tea

+0

@ time4tea: Infatti non è valido nemmeno Java, ma con i due punti mancanti e l'implicazione che lo specificatore di accesso è stato visto come qualcosa unito alla dichiarazione, è dannatamente avvincente rispetto a C++! –

+0

La sintassi era il mio errore di battitura, vedi il mio commento al post di apertura :) mi dispiace per quello. Inoltre, il 'Derived :: Interface :: method()' è il mio tentativo di definire una funzione che dovrebbe essere ereditata da Interface. La mia domanda originale era qualcosa di simile "posso implementare (definire) una funzione pura virtuale ereditata senza dichiararla esplicitamente nel file' .h' della classe derivata? ". La ragione per cui mi piacerebbe farlo è di evitare di ingombrare il mio file di intestazione quando la classe eredita da diverse interfacce, contenenti diversi virtual puri ciascuno ... – Neo

11

Devi dichiarare il tuo metodo nella sottoclasse.

// 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

Penso che intendiate ** dichiarare ** (non definire). –

+0

@ MikeSlutsky sì, l'ho fatto. – robert

+0

@robert Grazie per la risposta. Puoi discutere delle ragioni per questo? Provenendo da Java sembra molto sporco doverlo fare. Quando abbiamo molte classi derivate e molti metodi nell'interfaccia di base, abbiamo bisogno di cambiare molti file in caso di modifica nell'interfaccia di base. –

Problemi correlati