Reputation: 78
So I have a problem to override a pure virtual function in my derived class. The implementation and declaration of the classes looks like this:
class Base{
private:
size_t id;
public:
virtual bool isEqual(const Base& src) const =0;
};
class Derived: public Base{
private:
string str;
public:
virtual bool isEqual(const Derived& src) const override
{
return (this->str == src.str);
}
};
so when I implement it like this it hits me with compiler error like
member function declared with 'override' does not override a base class member function
Could you plz tell me how I could get that right and maybe explain me why my version doesn't work. Thanks in advance!
Upvotes: 4
Views: 2456
Reputation: 6805
The principle of polymorphism is that a Derived
is a Base
. If you want to override a function, the signature must be the same.
The proper way to solve your issue is to define your override as something equivalent to:
bool Derived::isEqual(const Base & src) const
{
try
{
Derived & d = dynamic_cast<Derived &>(src);
return (this->str == d.str);
}
catch(const std::bad_cast & e)
{
// src is not a Derived
return false;
}
}
If you want to work with pointers, you can do the same as follows:
bool Derived::isEqual(const Base * src) const
{
const Derived * d = dynamic_cast<const Derived*>(src);
if(d == nullptr) // src is not a Derived*
return false;
else
return (this->str == d->str);
}
Of course it assumes that you have a matching definition in Base
to override.
The solution provided by @Aconcagua uses the same idea in a more elegant way. I would advise to use his solution instead.
Upvotes: 3
Reputation: 25516
You cannot change the function signature that way – read about co- and contravariance for details and why C++ disallows both for function parameters (covariant return types are allowed).
On the other hand, if the other object is referred to via reference to base, the overriding (actually: overloading!) function would not be called at all:
Derived d1;
Derived d2;
Base& b2 = d2;
d1.isEqual(b2); // how do you imagine the derived version to get called now???
Key to a solution is a dynamic_cast
:
struct Base
{
virtual ~Base() { }
virtual bool operator==(Base const& other) = 0;
};
struct Derived : Base
{
bool operator==(Base const& other) override
{
auto o = dynamic_cast<Derived const*>(&other);
return o && o->str == this->str;
}
};
Note that I renamed the function to operator==
; this is far more natural in C++. With that, you can compare in the example above with:
bool isEqual = d1 == b2;
Edit:
The teacher told us that we must not overload operator
Well, then just revert the renaming... Actually, operators are just as ordinary functions as any other one else, solely that calling syntax differs (actually: an alternative variant exists, you could always call as d1.operator ==(d2)
, too).
Upvotes: 8