Why doesnt this function overide the base class function - c++

So here is the base class:
class MovieRepo {
protected:
MyLista<Movie> all;
public:
MovieRepo();
void store(const Movie& m);
}
And this one is the override:
class RepoFile : public MovieRepo
{
private:
string filename;
void loadFromFile();
void storeToFile();
public:
RepoFile(string _filename) : filename{ _filename } { this->loadFromFile(); };
void store(const Movie& m) override { // here is the error
MovieRepo::store(m);
storeToFile();
}
}
It says:'RepoFile::store': method with override specifier 'override' did not override any base class methods

MovieRepo::store() is not a virtual function. The override specifier only works with virtual functions. Change the base class method to a virtual method to fix the issue.

The override keyword can only be used when the function it's overriding is virtual. (It is, effectively, just a 'safer' way of specifying virtual in a derived class, so that you can spot cases where there is no matching base-class function.)
cppreference
Fix: Either remove the override keyword (the base-class function will still be overriden) or add virtual to the base-class function).

The key to the solution is the keyword virtual.
The virtual specifier specifies that a non-static member function is virtual and supports dynamic dispatch. It may only appear in the decl-specifier-seq of the initial declaration of a non-static member function (i.e., when it is declared in the class definition).
See this for why do we need virtual functions?. With "virtual" we get "late binding". Which implementation of the method is used gets decided at run time based on the type of the pointed-to object - what it was originally constructed as (not on the type of the pointer that you call through!).
If you want such "late binding" and want to invoke the right method (store) at run-time irrespective of the type of the pointer that you use to call store(), then go ahead with virtual functions with the implementation below:
Try this:
class MovieRepo {
public:
// ....
virtual void store(const Movie& m);
}
class RepoFile: public MovieRepo {
public:
void store(const Movie& m) override
{
// ....
}
}
More details on compilation warning/error:
The override keyword serves two purposes:
It shows the reader of the code that "this is a virtual method, that is overriding a virtual method of the base class."
The compiler also knows that it's an override, so it can "check" that you are not altering/adding new methods that you think are overrides.
In your case, compiler is warning you that the method your virtual function (in class RepoFile) isn't overriding any virtual function in base class.

Related

Why using a different return type in virtual function declaration throws an error instead of resulting in a redefinition?

Base class:
class Base
{
public:
virtual int f() const
{
return 1;
}
};
Derived class:
class Derived: public Base
{
public:
void f() const {}
};
Above code throws a "return type is not identical/covariant error".
I've read few discussions on it. This one is similar but they only say that it will break the code if the return types aren't identical/covariants.
Override a member function with different return type
Why the behavior I'm expecting doesn't happen?
Expected Behavior: The VPTR in Derived points to Base::f() (I've read incase an override isn't provided for a virtual function, Derived objects will just uses the inherited class version ). Also it hides the name f() so now a call like this:
Derived x;
x.f();
should've called Derived::f() and a call like this:
x.Base::f();
should've called the Base::f() function. This doesn't seem like breaking the code.
Incase its upcasted, even then it shouldn't break the code because VPTR for both classes points to the same Base::f()
The only reason I can think of is that such a declaration(same signature and covariant/identical return types) is reserved for overriding virtual methods and we just cannot use it to cause the behavior I'm expecting.
When the compiler encounters the matching signature (arguments, constness), it automatically makes the void f() const declaration virtual. So the definition of Derived is interpreted as:
class Derived: public Base
{
public:
virtual void f() const {} // virtual keyword is added
};
It clearly looks like an attempt to override Base::f(). All this happens because the function signatures match in the Base and Derived class. If the signatures didn't match, then only would this be a redefinition in which case it would've hidden the Base::f() in Derived class.

Using Virtual Function with Final keyword

I have a question about using the keyword final in C++. I understand that virtual function is a member function that is declared in the base class, and it is expected to be overridden in the derived classes. By dynamic binding, an appropriate method will be called, depending on the type of the object responsible for the call. However, to prevent a member function in a base class from being overridden in any derived class, we will use the final keyword.
void startEngine() final;// Compile error!
virtual void startEngine() final; //No error
Why we use "final" to PREVENT a member function in the base class from being overridden in derived class meanwhile we still have to use the keyword VIRTUAL (ALLOW to override) together.
I tried to delete the word virtual, but I got a compile error: "nonvirtual function cannot be declared with 'final' modifier"
First at all, we only can stop overriding functions if they can be overridden at all. So final only makes sense on virtual functions at all.
Still, final applied on a single class's virtual function might appear pretty meaningless. But if you consider a more complex hierarchy, matter changes:
class Parent
{
public:
virtual ~Parent() = default;
virtual void f();
};
class Child : public Parent
{
public:
void f() final; // f IS virtual already...
};
class GrandChild : public Child
{
// cannot override f any more – while Child still could!
};
Additionally, consider the following:
class Base
{
public:
virtual ~Base() = default;
void f(); // non-virtual! (i. e. cannot be overridden)
};
class Derived : public Base
{
public:
void f(); // does not override, but HIDEs Base::f!!!
};
Declaring Base::f both virtual and final would prevent hiding as well (but not overloading).
Actually, again this scenario rather makes sense if Base itself already inherited from another polymorphic class. If not and Base is not intended to be inherited, I'd not introduce any virtual functions at all (virtual function calls are more costly than normal function calls!). If then a user still inherits and hides a function – well, his own responsibility...

Do overriding functions need to be specified virtual?

In Cplusplus, in a derived class, if we define a member function to override a member function in its parent class, do we need to declare the one in the derived class to be virtual?
For example, do we need to declare g to be virtual in B in order for it to override A::g? which one of the following is correct for the above purpose?
class A{
public:
void f(){printf("A");}
virtual void g(){printf("A");}
}
class B : public A{
public:
void f(){printf("B");}
void g(){printf("B");}
}
or
class A{
public:
void f(){printf("A");}
virtual void g(){printf("A");}
}
class B : public A{
public:
void f(){printf("B");}
virtual void g(){printf("B");}
}
Thanks.
Once a method is virtual in a class, its child class has also these virtual class even if you don't add virtual to them.
Adding override is a good habit to avoid subtle error:
class A{
public:
void f() { printf("A"); }
virtual void g() { printf("A"); }
};
class B : public A{
public:
void f() { printf("B"); }
void g() override { printf("B"); }
};
No you don't. The function is virtual from the first point in the hierarchy where you declare it as such.
You can and should specify it as override in c++11 and onward. It specifies explicitly to the compiler that you are trying to override a virtual function in a base class. It than emits an error if you misspell the function name, mistype the parameters or do anything else that can be considered as adding an overload of the function. Prior to c++11, the previous mistakes would silently compile.
Defining member functions virtual in derived classes is optional. You can make the override explicit using C++11's override.
They both do the same thing. You don't need to explicitly say virtual in the derived class, as long as it is virtual in the base class.
In Cplusplus, in a derived class, if we define a member function to override a member function in its parent class, do we need to declare the one in the derived class to be virtual?
From the working draft, [class.virtual]/2 (emphasis mine):
If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list, cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf.
So, no. It is not required.
In pre-C++11 era, declaring virtual also the member functions in the derived classes helped the readers understanding what's going on under the hood.
Since C++11, override is the preferred way, for it not only helps the readers, but also it forces a compile-time check so that typos in the declarations don't introduce subtle errors.

overriding a const method of the Base class from the derived class

class Base{
//...
public:
int get()const{ // const
// Do something.
}
int get(int x){
// Do Someting.
}
//...
};
class Derived:public Base{
//....
public:
int get(){ // not const (not the same signature as the one is the base class)
//Dosomething
}
//...
};
I know that get() in Derived class will hide get() and get(int x) methods inside Base class. so My question is:
1) is this consedred overloading or overriding ?
2) does making get() const in the derived class will change something about (hiding or not hiding Base class methods).
Quote from a c++ book:
"It is a common mistake to hide a base class method when you intend to override it, by
forgetting to include the keyword const. const is part of the signature, and leaving it off
changes the signature, and thus hides the method rather than overrides it. "
It is neither overloading nor overriding. Rather, it is hiding.
If the other function were also visible, it would be overloading, which you can achieve with using:
class Derived : public Base
{
public:
using Base::get;
int get();
};
Even if you declared int get() const in the derived class, it would merely be hiding the base function, since the base function is not virtual.
Neither, it's just "hiding".
No. Hiding occurs based on function name, not on function signature.
Your quote is only relevant if you've declared the base-class functions virtual; you cannot override a non-virtual function.
Overloading is a function named the same, but with a different signature.
Overriding is overriding a signature that already exist.
You have just "hidden", which is neither.
A quick google search reveals this:
http://users.soe.ucsc.edu/~charlie/book/notes/chap7/sld012.htm which you may find helpful.

How to override non-virtual functions?

The very new syntax of override allows to let the compiler to report an error, if one does not really override a virtual function N3206.
class Base {
virtual void vfunc();
void afunc();
};
The following cases will be an error in class Derived : public Base, as mentioned in the Std examples:
void vfunk() override; // err: typo
void vfunc(int) override; // err: argument
void vfunc() const override; // err: cv
But what if the base method is not virtual?
void afunk() override; // ?
void afunc(int) override; // ?
void afunc() const override // ?;
The spec draft (n3242) says
If a virtual function is marked with the virt-specifier override and does not override a member function of a base class, the program is ill-formed.
Since the function declarations you show are not virtual, you also run afoul of
A virt-specifier-seq shall contain at most one of each virt-specifier. The virt-specifiers override and final shall only appear in the declaration of a virtual member function.
Note that a function that has the same name and parameter list (including constness) as a base function, but that is not virtual does not override that base function. It is instead said to hide the base function.
Designating that a function hides a base function by putting new instead of override after the function's declaration was part of the C++0x draft, but will not be part of C++0x as there were problems with finding syntax spots for non-function members for putting new at, in time. Consequently, it was voted out for C++0x.