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.
Related
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.
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.
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.
Can a pure virtual function (i.e one that has = 0 on the end) be overridden by an inherited class with a constant pure virtual function and still get called?
#include <stdio.h>
struct cBaseClass {
virtual void VirtualFunction () = 0;
};
struct cInheritedClass : cBaseClass {
virtual void VirtualFunction () const {
printf ("I'm a constant virtual function that"
" overrided a pure virtual function!\n");
}
}
};
int main() {
cBaseClass *Foo = new cInheritedClass;
Foo->VirtualFunction ();
}
The last line should result in cInheritedClass::VirtualFunction being called, not cBaseClass::VirtualFunction. I'm hoping that a constant function is just a compiler directive to make sure nothing inside the class gets written too and doesn't effect inheritance. I'm using this in my level class for some of the collision routines, where it would be nice to specify if the function can modify the class on a per Object/Class basis.
const and volatile qualifiers do form part of the function's signature, so a const function won't override a non-const one. My compiler rejects your code for this reason:
error: cannot allocate an object of abstract type ‘cInheritedClass’
note: because the following virtual functions are pure within ‘cInheritedClass’:
note: virtual void cBaseClass::VirtualFunction()
In C++11 or later, you can declare that the function should be an override:
void VirtualFunction () const override // "virtual" is optional when overriding
to get better diagnostics even if you don't try to instantiate the class:
error: ‘virtual void cInheritedClass::VirtualFunction() const’ marked override, but does not override
override and final specifier has been introduced in C++11.The below program uses these specifier as follows:
#include<iostream>
template<typename T>
void display(const T& val) { std::cout<<val<<"\n"; }
class Shape {
public:
virtual ~Shape()= default;
virtual void Draw() { display("Shape::Draw()");}
virtual void DisplayName() { display("Shape");}
};
class Circle : public Shape {
public:
virtual ~Circle() = default;
virtual void Draw() override final { display("Circle::Draw()");}
virtual void DisplayName() override { display("Cicle");}
};
int main()
{
}
In the above sample program Circle::Draw() has been defined as override final specifier. This compiles successfully however if the same method is defined as final override, then it throws an compile time error.
Wanted to understand the use cases of override and final specifier for the same method for a class?. When we should use it in our program?
In my opinion it is a compiler bug. At least at www.ideone com the code is compiled successfully.
Acoording to the C++ Standard (10.3 Virtual functions)
4 If a virtual function f in some class B is marked with the
virt-specifier final and in a class D derived from B a function
D::f overrides B::f, the program is ill-formed.
[ Example:
struct B {
virtual void f() const final;
};
struct D : B {
void f() const; // error: D::f attempts to override final B::f
};
—end example ]
A class may not be a derived class of itself. So the code you showed shall be compiled.
Also
5 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.
[ Example:
struct B {
virtual void f(int);
};
struct D : B {
virtual void f(long) override; // error: wrong signature overriding B::f
virtual void f(int) override; // OK
};
—end example ]
In your example function Draw of class Circle is marked with virt-specidier override and indeed overrides the function of the base class.
This is a compiler bug. According to the grammar that the C++11 standard is specifying in [class.mem]:
member-declarator: declarator
virt-specifier-seqopt pure-specifieropt
declarator
brace-or-equal-initializeropt
identifieropt
attribute-specifier-seqopt : constant-expression
virt-specifier-seq:
virt-specifier
virt-specifier-seq
virt-specifier virt-specifier:
override
final
The virt-specifier-seq doesn't imply any order in the virt-specifiers in the declaration.
When we should use it in our program?
This question might be worth looking at.
It looks like Vlad from Moscow is correct
From the override specifier at cppreference.com:
declarator virt-specifier-seq(optional) function-body
In both cases, virt-specifier-seq, if used, is either override or final, or final override or override final.
And again for the final specifier at cppreference.com:
declarator virt-specifier-seq(optional) function-body
virt-specifier-seq, if used, is either override or final, or final override or override final.
Compiler bugs aside, I would encourage you to pick an order and stick to it consistently - don't mix and match the word order through your codebase.