overriding pure virtual operators
Asked Answered
P

3

5

I'm trying to create a counter interface that forces all derived classes to implement this interface:

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;
};

However, just including this class definition results in the error below.

Unfortunately post inc can't be defined as reference.

Any ideas how to resolve this chicken/egg problem?

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)’
Prurigo answered 14/12, 2012 at 12:11 Comment(0)
G
5

You're out of luck. You want to return a value with the dynamic type of the object the function is called on. You can't: (non-pointer) values in C++ can't be covariant return types because a return-by-value in C++ can't have a different dynamic type from its static type.

It's basically the same problem as implementing a virtual clone(). It can't return by value. You'd be in trouble even if CounterInterface wasn't an abstract class, but instead of noticing it when the code fails to compile, you'd notice it when the returned object gets sliced.

What you could do is expand on the design. Write a class that holds a (smart) pointer to an instance of CounterInterface. This type can be returned by value and hence can implement the interface you want. It can do that by calling a pure virtual function CounterInterface *clone() (or unique_ptr<CounterInterface> clone()) that allocates and returns a new instance of the concrete class that implements the interface. For the operators that do work as virtual functions, you can leave them on CounterInterface and your wrapper class can call through, or you can rename them in the virtual interface:

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();
    }
};

Virtual operator== is a whole separate problem which I'll leave to other questions on the site.

Btw, CounterInterface needs a virtual destructor.

Grosso answered 14/12, 2012 at 12:17 Comment(0)
T
2

You cannot instantiate a class with pure virtual member functions. Since you cannot create them, you also cannot return them by value, as you do in

virtual CounterInterface  operator ++ (int) = 0;
virtual CounterInterface  operator -- (int) = 0;
Tristich answered 14/12, 2012 at 12:16 Comment(0)
G
1

First of all you shall replace

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

by

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

Secondly, the same thing that said 'Olaf Dietsche', it was faster than me :-)

Gourami answered 14/12, 2012 at 12:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.