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
Related
This question already has an answer here:
method in the derived class got executed without a *virtual* keyword in the referred class
(1 answer)
Closed 2 years ago.
Probably, i misunderstood c++ polymorphism(virtual function).
Please point me what i miss.
the source code is below
#include <iostream>
using namespace std;
class A {
public:
virtual void print(void) {
cout<<"class A"<<endl;
}
};
class B : public A {
public:
void print(void) {
cout<<"class B"<<endl;
}
};
class C : public B {
public:
void print(void) {
cout<<"class C"<<endl;
}
};
int main() {
A a;
B b;
C c;
A *pAa = &a;
A *pAb = &b;
A *pAc = &c;
B *pBc = &c;
pAa->print();
pAb->print();
pAc->print();
pBc->print(); // shouldn't be "class B"
return 0;
}
result
------------------------------
class A
class B
class C
class C // shouldn't be "class B"
my understanding is that
the last print statement should print "class B"
because pBc is a pointer of class B and the print function in class B is non virtual member function. i could not find the answer about this situation.
please tell me why or point me where i can find the answer and
understand c++ polymorphism in comprehension.
thanks.
If a function with a given signature is declared as virtual in a top-level base class, then the function is virtual in all derived classes no matter if it is marked with the keyword virtual (override, final) or not:
virtual function specifier
Then this function in the class Derived is also virtual (whether or not the keyword virtual is used in its declaration)
struct Base {
// Pure virtual function.
virtual void foo() const = 0;
};
struct A : public Base {
// Overriding virtual function, even if it
// is not marked as virtual (override, or final).
void foo() const {}
};
In A, adding the virtual specifier to foo() would only bring semantic value; it will be no functional difference whether virtual is omitted or not (unless someone changes the interface in Base).
Many static analyzers enforce(1) marking derived virtual functions with override or final, for two reasons:
semantics; clearly showing the given function is a virtual function (as per being defined so higher up in the inheritance chain), and
enforcement; if a function is marked as override and final but is not actually an overriding function, you will get a compiler error, which can be particularly useful to protect against mistakes when changing a base class interface (whilst forgetting which classes that actually implements this interface).
E.g.:
struct Base {
// Pure virtual function.
virtual void foo() const = 0;
};
struct A : public Base {
// Overriding virtual function.
void foo() const override {}
};
struct B final : public Base {
// Overriding (final) virtual function.
void foo() const final {}
// Error: Function does not override.
// void bar() const override {}
};
(1) E.g. Rule A10-3-1 in the Autsar C++14 Language Guidelines (safety-critical development in automotive) is categorized as a required rule: Virtual function declaration shall contain exactly one of the three specifiers:(1) virtual, (2) override, (3) final.
the print function in class B is non virtual member function
No. Since A::print is marked as virtual and B inherits from A, then B::print is virtual too; regardless of the keywork virtual is specified on it or not.
(emphasis mine)
If some member function vf is declared as virtual in a class Base, and
some class Derived, which is derived, directly or indirectly, from
Base, has a declaration for member function with the same
name
parameter type list (but not the return type)
cv-qualifiers
ref-qualifiers
Then this function in the class Derived is also virtual (whether or not the keyword virtual is used in its declaration) and overrides Base::vf (whether or not the word override is used in its declaration).
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.
Here is the problem: I keep getting the unimplemented pure virtual method error when trying to compile. I have implemented all of the pure virtual methods in the abstract base class. Any ideas?
here is the abstract base class:
class record{
public:
virtual int getID()=0;
virtual record *clone();
};
and the implementation:
class sdata: public record{
public:
sdata(std::string s = ""){data=s; ID=atoi(data.substr(0,8).c_str());}
virtual int getID(){return ID;}
private:
std::string data;
int ID;
};
sorry, here is the complete error message:
Unimplemented pure virtual method 'getID' in 'record'
Perhaps this bit of code is causing the error then:
int hashTable::hash(record *x) {
return floor(m * (x->getID() * A - floor(x->getID() * A)));
}
Without seeing the code causing the error, it's difficult to know exactly what's going on. If this is a compile-time error, I don't see anything here that would cause it.
However, if you're seeing a runtime error, the two most common causes of this that I can think of are:
(1) Calling the member function from within the base class's constructor or destructor (even indirectly).
(2) The derived class calling the base class's version of the function without it being implemented.
An example showing both of these errors would be:
struct Base {
Base()
{
call_foo(); // Oops, indirectly calls Base::foo() (Scenario 1)
}
void call_foo() const {
foo();
}
protected:
virtual void foo() const = 0;
};
struct Derived : Base {
protected:
virtual void foo() const {
Base::foo(); // Oops, unimplemented virtual base function (Scenario 2)
}
};
int main() {
Derived().call_foo();
}
== UPDATE: Possible compile-time error ==
I observe in your example code that record has a non-pure-virtual clone() member function returning a record *. Since record is abstract, you can't create a record directly (only its concrete subclasses). This suggests that your clone() member function should probably also be pure virtual; if it tries to (for example) return new record(), you will get an error that your base class has pure virtual functions.
It sounds like you have not implemented all the functions from the abstract base class. If a function in your base has the signature:
void SomeFuction() const;
And you implement the following in your derived class:
void SomeFuction();
Then you have have not implemented the function because you omitted the const. GCC should tell you what you did not implement.
Related: if you had a concrete implementation of the base, you would have hidden its name in the derived class. To find functions you are [accidentally] hiding, use -Woverloaded-virtual.
This has the feeling of a complete newbie question, but why does the following code not compile when the final specifier is used for B::operator()?
struct A
{
virtual void operator()() const = 0;
};
// the CRTP-component is not really necessary here
// but it possibly makes more sense in that it could be applied like this in reality
//
template<typename Derived>
struct B : A
{
virtual void operator()() const override final
{
static_cast<Derived const&>(*this).operator()();
}
};
struct C : B<C>
{
void operator()() const
{
//do something
}
};
int main()
{
C()();
}
G++ prints the following error message:
main.cpp:17:14: error: virtual function 'virtual void C::operator()() const'
void operator()() const
^
main.cpp:9:22: error: overriding final function 'void B<Derived>::operator()() const [with Derived = C]'
virtual void operator()() const override final
^
I would have thought it works as the non-virtual C::operator() does not override the virtual functions in its base classes? How can I bring this to work (--without changing the name of C::operator())?
EDIT: As pointed out by several users, the answer is simply that the virtual-keyword in the derived class is redundant (whereas I thought leaving it out would prevent from inheriting). However, the goal I had in asking this -- namely a consistent interface throughout the dynamic and static inheritance hierarchy -- can be solved by using a non-virtual operator[] throughout and couple classes A and B by a virtual function apply:
struct A
{
void operator()() const
{
this->apply();
}
protected:
virtual void apply() const = 0;
};
template<typename Derived>
struct B : A
{
void operator()() const
{
static_cast<Derived const&>(*this).operator()();
}
protected:
virtual void apply() const override final
{
this->operator()();
}
};
struct C : B<C>
{
void operator()() const
{
//do something
}
};
int main()
{
C()();
}
If a function is declared virtual in a base class, then a function declared with the same name and parameter list is implicitly virtual in derived classes, whether or not you use the virtual keyword. You cannot make C::operator()() non-virtual.
A function in a derived class with the same signature as a virtual function in a base class overrides that virtual function from the base class. That makes it a virtual function, even if/though the declaration in the derived class doesn't use the virtual key word.
That can't be changed, so if you really need to have a function with the same name in a derived class that doesn't override the virtual function from the base class (and in the process, become virtual itself and in this case, violate the final in B) you'll need to change the signature of the function in the derived class. That can mean a different name, different parameter list, or different qualifiers. I'd treat the latter two with extreme caution though--the compiler will be able to sort out the mess you've made, but many human readers may (very easily) be surprised.
If I were reviewing such code, I'd probably cite this as a problem, and the author would need to provide very solid reasoning for why it was truly necessary to get it approved.
As an override (because it has the same signature as the virtual function in a base class), the override conflicts with the final specified in its base class.
One fix (or rather workaround) is to give that function a defaulted argument, so that it has a different type and hence not an override, and a better approach is to fix the design.
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.