Why is it allowed to overide non-virtual function? - c++

I'm experimneting with inheritance in C++.
struct A {
virtual void foo(){ std::cout << "foo()" << std::endl; }
void bar(){ std::cout << "bar()" << std::endl; }
};
struct B : A{
void foo(){ std::cout << "derived foo()" << std::endl; }
void bar(){ std::cout << "derived bar()" << std::endl; }
};
struct C : B {
void foo(){ std::cout << "derived derived foo()" << std::endl; }
void bar(){ std::cout << "derived derived bar()" << std::endl; }
};
int main()
{
B* b = new C();
b->foo(); //derived derived foo()
b->bar(); //derived bar()
}
LIVE DEMO
Since, the function foo declared as non-virtual in the struct B I expected that B's function would be called. But foo which one from C was. Why? I change the "virtual status" of the function in B. Why is it still virtual?

foo() is declared as virtual function in the base class A, so foo() in all the derived class will be virtual too.
From the standard, 10.3$2 Virtual functions [class.virtual] (bold by me)
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 (8.3.5),
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.

Once virtual always virtual.
Since foo is virtual in A it will be virtual in all classes derived from A - whether or not they get the virtual keyword.

Above mention answers are valid, but can we use override keyword, because
The override special identifier means that the compiler will check the
base class(es) to see if there is a virtual function with this exact
signature. And if there is not, the compiler will indicate an error.
so something like this is struct B:
void bar() override

Related

calling a base function on a derived object

class base{
public:
virtual void foo(){
std::cout << "base::foo was called" << std::endl;;
}
void bar(){
foo();
std::cout << "base::bar was called" << std::endl;;
}
};
class derived : public base {
public:
void foo() {
std::cout << "derived::foo was called" << std::endl;
}
};
int main() {
derived der;
der.bar();
// desired output = "base::foo was called" "base::bar was called"
// actual output = "derived::foo was called" "base::bar was called"
}
Am I missing something obvious here?
Why does the bar() function when called on an object of derived class call the derived::foo function, even though the function itself only exists in the base class.
When a member function in a derived class overrides a virtual member function in a base class like this, that means it entirely replaces the function definition for most purposes. So calling the function foo on the object der created in main will usually use the Derived::foo definition. This behavior is consistent whether the code calling foo is in a member of Derived, or a member of Base, or neither class.
The two major exceptions are:
If you use a "qualified-id" class_type::func_name syntax to call the function, that disables the virtual function logic and just calls the function you named (after normal name lookup and overload resolution).
So since you say you want the program to call base::foo, change base::bar like:
void bar() {
base::foo();
std::cout << "base::bar was called" << std::endl;
}
During a constructor or destructor of the base class, the function from the base class (or one of its bases) will be called, ignoring overriders in the derived class(es). The object is considered to not yet or no longer be an object of the derived type. (And if the derived function were called and uses any derived members which are not yet created or already destroyed, this would be trouble.)
base::foo is declared virtual, hence uses virtual dispatch. If you don't want that then call base::foo explicitly:
struct base{
virtual void foo(){
std::cout << "base::foo was called" << std::endl;;
}
void bar(){
base::foo();
std::cout << "base::bar was called" << std::endl;;
}
};
(note that all methods are private in your example, I suppose thats just a typo)
When you declare a function virtual, the compiler will generate a vtable for each object created, and in your case, since the object is a derived the function vtable will always point to derived::foo() for that instance.

C++ virtual class method

Imagine I have a super class A in C++ that has a virtual method. If I want to override it on my class B and still keep it virtual is it recommended to keep the virtual keyword on the class B on can I ignore it because I already said that method is virtual on the super class?
For example what is the correct way to do the following.
Method A:
class A{
public:
virtual void hello(){
std::cout << "Hello World!" << std::endl;
};
};
class B: public A{
public:
virtual void hello() override{
std::cout << "Hello Sun!" << std::endl;
};
};
class C: public B{
public:
virtual void hello() override{
std::cout << "Hello Moon!" << std::endl;
};
};
Or declaring the function as virtual only on the first class.
Method B:
class A{
public:
virtual void hello(){
std::cout << "Hello World!" << std::endl;
};
};
class B: public A{
public:
void hello() override{
std::cout << "Hello Sun!" << std::endl;
};
};
class C: public B{
public:
void hello() override{
std::cout << "Hello Moon!" << std::endl;
};
};
I want to use late biding in all situations. So I need the hello() method to be virtual in the three classes. Both ways worked on CodeBlocks but I don´t know what is the best way or even if there is any difference between them.
virtual is superfluous for B and C, and the effect is exactly the same. The important thing is to always mark your methods with override1 if they're meant to override a virtual method. While this is not strictly necessary, it is a good practice. You're doing that correctly in both examples.
Pertinent standardese:
n4140
§ 10.3 [class.virtual] / 2
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 refqualifier (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.
1 override as a specifier is available since C++11.

Polymorphism with 3 classes in C++

The following code prints 1 2, but I would expect it to print 1 1.
#include <iostream>
using namespace std;
class A {
public:
virtual void f() { cout << "0" << endl; }
};
class B : public A{
public:
void f() { cout << "1" << endl; }
};
class C : public B{
public:
void f() { cout << "2" << endl; }
};
int main() {
A *pa = new B();
B *pb = new C();
pa->f();
pb->f();
}
In my understanding, pa->f() executes B's f() function since A's is virtual, but why does pb->f() execute C's f() function when B's f() is not virtual.
Additionally, if I remove 'virtual' from class A, it prints 0 1, which makes sense because A and B execute their own f() functions since they aren't virtual. How come pb->f() changes if it isn't affected since it's only A that changes?
but why does pb->f() execute C's f() function when B's f() is not virtual.
Because the dynamic type of pb is C and C::f is indeed virtual. When you declare
virtual void f();
in the base class, every other void f() of the derived classes in the hierarchy is also virtual, as per §10.3/2:
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 (8.3.5), 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 overrides112 Base::vf.
(emphasis mine)
In fact:
class A {
public:
virtual void f() { cout << "0" << endl; }
};
class B : public A{
public:
virtual void f() { cout << "1" << endl; }
};
class C : public B{
public:
virtual void f() { cout << "2" << endl; }
};
is equivalent to your code. It just so happens that the C++ standard allows virtual to be omitted in those cases.
It happens because writing virtual keyword in subclasses is not necessary, it just improves readability.

Why is this method behaving as virtual when its not marked as virtual?

Suppose I have the following code
class base
{
public:
virtual void MyVirtual() { std::cout << "This is base MyVirtual \n";}
void NonVirtual() { std::cout << "This is base NonVirtual \n";}
};
class derA : public base
{
public:
void MyVirtual() { std::cout << "This is derA MyVirtual \n";}
void NonVirtual() { std::cout << "This is derA NonVirtual \n";}
};
class derB : public derA
{
public:
void MyVirtual() { std::cout << "This is derB MyVirtual \n";}
void NonVirtual() { std::cout << "This is derB NonVirtual \n";}
};
int main()
{
derA *da = new derB;
da->MyVirtual(); // "This is derB MyVirtual \n"
da->NonVirtual();
std::cin.get();
return 0;
}
Now my question is why is MyVirtual Method behaving as virtual when it is not marked as virtual in class derA ?
In C++ inherited virtual functions remain virtual in the derived class even without the virtual keyword. It is considered good practice to write virtual for every inherited function.
Update
As pointed out in the comments in C++ 11 it is considered good practice to include the keyword override immediately after the declarator. This catches a common class of errors and explicitly makes the intention clear in the code.
As per the Standard § 10.3 Point #2
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 refqualifier (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.
There goes your answer, straight from the standards. So, it doesn't matter if you have used the keyword virtual in your derived class or not.

Does derived class' member functions inherit virtualness from base class?

Say we have the following two classes, A is the base class with virtual destructor and B is the derived class whose destructor doesn't have 'virtual' qualifier. My question is, if I going to derive more classes from B, will B's destructor automatically inherit the virtualness or I need to explicitly put 'virtual' before '~B() {...}'
class A
{
public:
A() { std::cout << "create A" << std::endl;};
virtual ~A() { std::cout << "destroy A" << std::endl;};
};
class B: A
{
public:
B() { std::cout << "create B" << std::endl;};
~B() { std::cout << "destroy B" << std::endl;};
};
From C++ standard (section 10.3):
If a virtual member function vf is declared in a class Base and in
a class Derived, derived directly or indirectly from Base, [...]
then Derived::vf is also virtual (whether or not it is so declared).
So yes.
If base class method is virtual then all the subsequent derived class methods will become virtual. However, IMO it's a good programming practice to put virtual ahead of the method; just to indicate the reader the nature of the function.
Also note that there are some corner case where you might get unexpected results:
struct A {
virtual void foo(int i, float f) {}
};
sturct B : A {
void foo(int i, int f) {}
};
Here actually, B::foo() is not overriding A::foo() with virtual mechanism; rather it's hiding it. So irrespective of you make B::foo() virtual, there is no advantage.
In C++0x, you have override keyword, which overcomes such problems.
Virtualness is inherited all the way down. You only need to specify it in the top base class.
This is true for destructors as well as normal member functions.
Example:
class Base { virtual void foo() { std::cout << "Base\n"; } };
class Derived1 : public Base { void foo() { std::cout << "Derived1\n"; } };
class Dervied2 : public Derived1 { void foo() { std::cout << "Derived2\n"; } };
int main()
{
Base* b = new Base;
Base* d1 = new Derived1;
Base* d2 = new Derived2;
Derived1* d3 = new Derived2;
b->foo(); // Base
d1->foo(); // Derived1
d2->foo(); // Derived2
d3->foo(); // Derived2
}
or I need to explicitly put 'virtual' before '~B() {...}'
No, you need not, although you can put virtual here to make code more clear for the reader. This applies not only for destructors but for all member functions.