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.
Related
I was studying on effects of virtual keyword in C++ and I came up with this code.
#include<iostream>
using namespace std;
class A {
public:
virtual void show(){
cout << "A \n";
}
};
class B : public A {
public:
void show(){
cout << "B \n";
}
};
class C : public B {
public:
void show(){
cout << "C \n";
}
};
int main(){
A *ab = new B;
A *ac = new C;
B *bc = new C;
ab->show();
ac->show();
bc->show();
}
The expected output is:
B
C
B
Since show function in B is non-virtual. But the outcome when you compile this is:
B
C
C
It behaves as if show function in B is virtual. Why is this the case? Does B class gets overridden here? How come I point to the A class if I'm pointing a C class to the B class?
According to the C++ 2017 Standard (10.1.2 Function specifiers)
2 The virtual specifier shall be used only in the initial declaration
of a non-static class member function; see 13.3.
And (13.3 Virtual functions)
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 (11.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 overrides111 Base::vf. For convenience we say that
any virtual function overrides itself. A virtual member function C::vf
of a class object S is a final overrider unless the most derived class
(4.5) of which S is a base class subobject (if any) declares or
inherits another member function that overrides vf. In a derived
class, if a virtual member function of a base class subobject has more
than one final overrider the program is ill-formed.
Thus the function show in the class B is a virtual function because it has the same signature as the function declared in the class A.
Consider a more interesting example when in the class B there is added the qualifier const to the member function show.
#include<iostream>
using namespace std;
class A {
public:
virtual void show(){
cout << "A \n";
}
};
class B : public A {
public:
void show() const{
cout << "B \n";
}
};
class C : public B {
public:
void show() {
cout << "C \n";
}
};
int main(){
A *ab = new B;
A *ac = new C;
B *bc = new C;
ab->show();
ac->show();
bc->show();
}
In this case the output will look like
A
C
B
In this expression statement
ab->show();
there is called the virtual function show declared in the class A.
In this statement
ac->show();
there is called the same virtual function that is overridden in the class C. The compier uses the virtual function declaration in the class A because the static type of the pointer ac is A *.
In this statement
bc->show();
there is called non-virtual member function show with the qualifier const because the static type of the pointer bc is B * and the compiler finds the function in the class B that hides the virtual function declared in the class A..
For the original program you could use the specifier override to make the class definitions more clear. For example
#include<iostream>
using namespace std;
class A {
public:
virtual void show(){
cout << "A \n";
}
};
class B : public A {
public:
void show() override{
cout << "B \n";
}
};
class C : public B {
public:
void show() override{
cout << "C \n";
}
};
int main(){
A *ab = new B;
A *ac = new C;
B *bc = new C;
ab->show();
ac->show();
bc->show();
}
You don't need to specify a function as virtual in derived class, if specified in the base class.
The behaviour is the correct one. Since the show function is virtual, the version invoked will be the one attached to the instance you're calling it on, rather than the one described by the type of that instance (which can be a base of that instance's real type).
This question already has answers here:
What's the difference between the Derived class override the base class's virtual function with or not with a "virtual" prefix? [duplicate]
(2 answers)
Closed 5 years ago.
I have three following classes:
class A
{
private:
std::string device;
public:
std::string getDeviceType() { return device; };
void setDeviceType(std::string device) { device = device; };
virtual void doSomething() = 0;
virtual void doSomething2() = 0;
};
class B: public A
{
private:
public:
B(){ ; };
virtual ~B(){ ; };
void doSomething() { std::cout << "I am usual B" << std::endl; };
void virtual doSomething2() { std::cout << "I am usual B" << std::endl; };
};
class C : public B
{
private:
public:
C(){ ; };
~C(){ ; };
void doSomething() { std::cout << "I am C" << std::endl; };
void doSomething2() { std::cout << "I am C" << std::endl; };
};
main:
B *myHandler = new C();
myHandler->doSomething();
myHandler->doSomething2();
but output is not as expected, my expected output was I am usual B and then I am C, because doSomething() is a non virtual member of class B. But the real output was I am C and then I am C. Do you know why?
because of doSomething() is non virtual member of class B
This is where you are mistaken. In A you declare doSomething() as virtual. That means that it is implicitly marked virtual in classes that derive from it. So doSomething() in B is virtual which means you will call C's doSomething().
The reason is that doSomething is marked as virtual in class A. So it remains virtual in classes B and C because they inherit from class A.
As this function is virtual, it is called according to the real type of the object, which is C in your case, and you get the output: I am C.
Once marked virtual, it remains virtual in all derived classes.
In C you overrode both doSomething() and doSomething2(). You instantiate C, so the methods of C are called in both cases.
If you omitted the override in C of doSomething(), the output would be as you expected it.
KR,
Melle
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
In the following code
#include <iostream>
using namespace std;
class A {
public:
A() {}
virtual ~A() {};
};
class B : public A {
public:
B() {}
virtual ~B() {};
};
void process(const A&) {
cout << "processing A" << endl;
}
void process(const B&) {
cout << "processing B" << endl;
}
int main(void) {
A* a = new B;
process(*a);
return 0;
}
the output of running it becomes
processing A
but I would have assumed that it should have been
processing B
since a points to the derived class B and not A. So why does it call the first implementation of process function and not the second?
The static type of expression *a is A because a was declared as
A* a = new B;
The compiler resolves the selection of overloaded functions using the static type of the argument.
Even when virtual functions are called the compiler uses the static type of the object to call appropriate function. The difference is only that the compiler uses the table of pointers to virtual functions to indirectly call the required function.
You need to make process() a virtual member function of A, B:
class A {
public:
A() {}
virtual ~A() {};
virtual void process() const { cout << "processing A" << endl; }
};
class B : public A {
public:
B() {}
virtual ~B() {};
virtual void process() const override { cout << "processing B" << endl; }
};
int main(void) {
A* a = new B;
a->process();
return 0;
}
In your current code, *a is of type A&, so the closest match to process(*a); is the first overload (for const A&).
void process(const A&); is a better (exact) match, since dereferencing A* gives you A&.
Short answer, but there isn't much more to say unless you want a reference from the standard.
You could dynamic_cast the result of *a and that would give you a B&, but that's smelly desing. What you probably want is a virtual function in A that's overriden in B (assume it's called foo). Then, calling a->foo() would dispatch to B::foo.
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.