2012-12-14 17 views
5

Próbuję utworzyć interfejs licznika, który zmusza wszystkich klas pochodnych do wdrożenia tego interfejsu:nadrzędne czyste operatorów wirtualnych

class CounterInterface 
{ 
public: 
    virtual CounterInterface& operator ++() = 0; 
    virtual CounterInterface operator ++ (int) = 0; 
    virtual CounterInterface& operator --() = 0; 
    virtual CounterInterface operator -- (int) = 0; 
    virtual bool operator == (const CounterInterface o) const = 0; 
    virtual operator uint32_t() const = 0; 
    virtual void reset() = 0; 
}; 

Jednak właśnie w tym także to definicja klasy rezultatów w poniższym błędem.

Niestety post inc nie może być zdefiniowany jako odniesienie.

Jakieś pomysły, jak rozwiązać ten problem z kurczakiem/jajkiem?

CounterInterface.h:25:29: error: invalid abstract return type for member function ‘virtual libceis::CounterInterface libceis::CounterInterface::operator++()’ 
CounterInterface.h:22:8: note: because the following virtual functions are pure within ‘libceis::CounterInterface’: 
CounterInterface.h:25:29: note: virtual libceis::CounterInterface libceis::CounterInterface::operator++() 
CounterInterface.h:26:29: note: virtual libceis::CounterInterface libceis::CounterInterface::operator++(int) 
CounterInterface.h:27:29: note: virtual libceis::CounterInterface libceis::CounterInterface::operator--() 
CounterInterface.h:28:29: note: virtual libceis::CounterInterface libceis::CounterInterface::operator--(int) 
CounterInterface.h:29:17: note: virtual bool libceis::CounterInterface::operator==(libceis::CounterInterface) const 
CounterInterface.h:30:12: note: virtual libceis::CounterInterface::operator uint32_t() const 
CounterInterface.h:31:17: note: virtual void libceis::CounterInterface::reset() 
CounterInterface.h:26:29: error: invalid abstract return type for member function ‘virtual libceis::CounterInterface libceis::CounterInterface::operator++(int)’ 

Odpowiedz

2

Nie można utworzyć instancji klasy z czystymi funkcjami wirtualnymi. Ponieważ nie można ich tworzyć, również nie może wrócić do ich wartości, jak to zrobić w

virtual CounterInterface operator ++ (int) = 0; 
virtual CounterInterface operator -- (int) = 0; 
1

Przede wszystkim zastępuje

virtual bool operator == (const CounterInterface o) const = 0; 

przez

virtual bool operator == (const CounterInterface &o) const = 0; 

Po drugie, ta sama Rzecz, która mówi "Olaf Dietsche", była szybsza ode mnie :-)

5

Nie masz szczęścia. Chcesz zwrócić wartość z dynamicznym typem obiektu, do którego funkcja jest wywoływana. Nie można: wartości (nieinterpektyw) w C++ nie mogą być kowariantnymi typami zwracanymi, ponieważ zwracana wartość w C++ nie może mieć innego typu dynamicznego niż typ statyczny.

Jest to zasadniczo ten sam problem, co implementacja wirtualnego clone(). Nie może zwrócić wartości. Wpadłbyś w kłopoty, nawet jeśli CounterInterface nie byłaby klasą abstrakcyjną, ale zamiast zauważać, gdy kod się nie skompilował, zauważyłbyś go, gdy zwracany obiekt zostanie podzielony na kawałki.

Co można zrobić, to rozwinąć projekt. Napisz klasę zawierającą (inteligentny) wskaźnik do instancji o numerze CounterInterface. Ten typ może być zwracany przez wartość, a zatem może zaimplementować odpowiedni interfejs. Może to zrobić, wywołując czystą funkcję wirtualną CounterInterface *clone() (lub unique_ptr<CounterInterface> clone()), która przydziela i zwraca nowe wystąpienie konkretnej klasy, która implementuje interfejs. Dla operatorów, którzy pracują jako funkcje wirtualne, można pozostawić je na CounterInterface i klasa wrapper można wywołać poprzez, czy można zmienić je w interfejsie wirtualnym:

class Counter { 
    unique_ptr<CounterInterface> ctr; 
    public: 
    Counter(unique_ptr<CounterInterface> c) : ctr(std::move(c)) {} 
    Counter(CounterInterface *c) : ctr(c) {} 
    Counter &operator++() { 
     ctr->increment(); // or ++(*ctr) 
     return *this; 
    } 
    Counter operator++(int) { 
     Counter ret(ctr->clone()); 
     ctr->increment(); 
     return ret; 
    } 
    operator uint32_t() const { 
     return *ctr; 
    } 
    void reset() { 
     return ctr->reset(); 
    } 
}; 

wirtualnej operator== to zupełnie odrębny problem, który ja Zostawię inne pytania na stronie.

Btw, CounterInterface potrzebuje wirtualnego destruktora.