Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return type is not identical to nor covariant with return type (operator++)

I have the following error:
IntelliSense: return type is not identical to nor covariant with return type "Counter" of overridden virtual function "Counter::operator++"

Here are the headers of my project.
counter.h

/* Header file of Counter Class*/
#pragma once
#include <iostream>
using namespace std;
//Class definition
class Counter {
    friend ostream &operator<<(ostream &out, const Counter &c);
    public:
        Counter(int n0 = 0);
        virtual Counter &operator++();
        virtual Counter operator++(int);
        void reset();
        int getCount() const;

    private:
        int count;
};

LimitedCounter.h

#pragma once
#include "counter.h"

class LimitedCounter : public Counter{
    friend ostream &operator<<(ostream &out, const LimitedCounter &c);
public:
    LimitedCounter(int low, int up);
    void reset();
    LimitedCounter& operator++();
    LimitedCounter operator++(int); // error here
    operator int() { return getCount(); };
    int getCount() const { return Counter::getCount(); };
private:
    int upper;

};

And the implementation
counter.cpp

/* Implementation of Counter Class*/

#include "counter.h"
#include <iostream>

Counter:: Counter(int n0) {
     count = n0;
}
Counter& Counter::operator++() {
   count++;
   return *this;
}
Counter Counter::operator++(int) {
   Counter old = *this;;
   count++;
   return old;
}
void Counter::reset(){
   count = 0;
}
int Counter::getCount() const{
   return count;
}
ostream &operator<<(ostream & out, const Counter &c) {
     out << "\nCounter value is now " << c.count ;
     return out;
}

LimitedCounter.cpp

#include "LimitedCounter.h"
LimitedCounter::LimitedCounter(int low, int up) : Counter(low), upper(up) {}

LimitedCounter& LimitedCounter::operator++() {
    if (getCount() < upper) {
        Counter::operator++();
    }
    return *this;
}

LimitedCounter LimitedCounter::operator++(int) {
    if (getCount() < upper) {
        LimitedCounter old = *this;
        Counter::operator++(0); // question?
        return old;
    }
    else {
        return *this;
    }
}

void LimitedCounter::reset() {
    Counter::reset();
}

//friend function
ostream &operator<<(ostream &out, const LimitedCounter &c) {
    out << c.getCount() << endl;
    return out;
}

I get the error:
error C2555: 'LimitedCounter::operator ++': overriding virtual function return type differs and is not covariant from 'Counter::operator ++'

When I remove virtual in the post-increment of counter.h then there is no error at all. So everything works fine with the pre-increment. So I don't know is it because how I implement the post-increment? And also when I override the post-increment ( operator++(int) ), is it right that I write like this:

Counter::operator++(0);

Thanks for helping me.

like image 226
Henry Tran Avatar asked Oct 23 '25 16:10

Henry Tran


1 Answers

The problem is simple: you are returning an object by value, so you have the following situation

virtual Counter Counter::operator++(int)
LimitedCounter LimitedCounter::operator++(int) override

Now, since the method is virtual, the correct implementation is chosen at runtime according to the vtable of the object you are calling it on.

This means that the compiler can't know a priori the type returned by operator++ but he needs to know at least its size since it's a value (and not just a pointer).

Indeed if you had the following situation would be accepted:

virtual Counter* Counter::operator++(int)
LimitedCounter* LimitedCounter::operator++(int) override

because the runtime implementation would in any case return a pointer so the compiler would be able to cope with it correctly.

The standard specifies what's allowed and considered covariant in §10.3 (C++11):

The return type of an overriding function shall be either identical to the return type of the overridden function or covariant with the classes of the functions. If a function D::f overrides a function B::f, the return types of the functions are covariant if they satisfy the following criteria:

  • both are pointers to classes, both are lvalue references to classes, or both are rvalue references to classes

  • the class in the return type of B::f is the same class as the class in the return type of D::f, or is an unambiguous and accessible direct or indirect base class of the class in the return type of D::f

  • both pointers or references have the same cv-qualification and the class type in the return type of D::f has the same cv-qualification as or less cv-qualification than the class type in the return type of B::f.

like image 174
Jack Avatar answered Oct 25 '25 09:10

Jack