2011-01-13 20 views
8

Mam pewne problemy z wdrażaniem czystych wirtualnych funkcji odziedziczonych po jakiejś abstrakcyjnej klasie, gdy klasy są podzielone na *.h i *.cpp files. Kompilator (g++) mówi mi, że klasa pochodna nie może być utworzona z powodu istnienia czystych funkcji.C++ implementacja czystych funkcji wirtualnych i plików nagłówkowych

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

Czy to oznacza, że ​​muszę zadeklarować metodę() dwukrotnie - w interfejsie użytkownika *.h aw derived.h też? Czy nie ma innej drogi?

+0

To nie jest prawidłowe C++. 'public void method() = 0;' bardziej przypomina Java. –

+0

Po pierwsze, nie ma powodu, aby mieć plik .cpp, w którym jedyną rzeczą jest pusta przestrzeń nazw. Nie potrzebujesz pliku implementacji dla nagłówka zawierającego klasę abstrakcyjną. – Falmarri

+0

@Falmarri jest poprawna. –

Odpowiedz

12

Zapomniałeś zadeklarować Derived::method().

Próbowałeś to przynajmniej zdefiniować, ale napisałeś Derived::Interface::method() zamiast Derived::method(), ale nawet nie próbowałeś go zadeklarować. Dlatego nie istnieje.

Dlatego Derived ma method() więc czystego wirtualnego funkcji method() z Interface nie została przesłonięta ... i dlatego Derived jest również czysto wirtualne i nie może być instancja.

Również, public void method()=0; nie jest prawidłowy C++; wygląda bardziej jak Java. Funkcje czystych wirtualnych elementów muszą być wirtualne, ale nie napisałeś virtual. Po specyfikacjach dostępu następuje dwukropek:

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

Luka w pustce prawdopodobnie jest literówką, nie jest też java. – time4tea

+0

@ time4tea: Rzeczywiście nie jest to poprawna Java, ale z brakującym dwukropkiem i implikacją, że specyfikator dostępu był postrzegany jako coś dołączonego do deklaracji, jest to cholernie bliższy widok niż C++! –

+0

Składnia była moja literówka, zobacz mój komentarz do posta otwarcia :) przepraszam za to. Ponadto, 'Derived :: Interface :: method()' jest moją próbą zdefiniowania funkcji, która powinna być dziedziczona z interfejsu. Moje oryginalne pytanie było czymś w rodzaju "czy mogę zaimplementować (zdefiniować) dziedziczoną czystą wirtualną funkcję bez jawnego deklarowania jej w pliku" .h' klasy pochodnej? ". Powodem, dla którego chciałbym to zrobić, jest uniknięcie zaśmiecania mojego pliku nagłówkowego, gdy klasa dziedziczy po kilku interfejsach, zawierających kilka czystych wirtualnych ... – Neo

11

Musisz zadeklarować swoją metodę w podklasie.

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

Myślę, że masz na myśli ** declare ** (nie definiuj). –

+0

@MikeSlutsky tak, zrobiłem. – robert

+0

@robert Dziękujemy za odpowiedź. Czy możesz opracować powody? Jadąc z Java wydaje się bardzo brudny, aby to zrobić. Kiedy mamy wiele różnych klas i wiele metod w interfejsie podstawowym, musimy zmienić wiele plików w przypadku zmiany interfejsu podstawowego. –

Powiązane problemy