I have a confusion about the inheriting the virtual property of a method.
Let's suppose we have 4 classes: class A, class B, class C and class D.
The classes are inherited by this way: A -> B -> C -> D, where A is the base class.
By this time, I'm sure about this: Beginning the class method declaration with virtual in a base class (class A), makes the method virtual for all classes derived from the base class, including the derived ones of the derived classes. (B and C class methods determined to be virtual).
The confusion is here. What if, in the base class A, there wouldn't be any virtual member. Instead, let's say, that class B declares a method to be virtual. I assume, that this change would make the function virtual for all the derived classes that belong to the inheriting chain (C and D classes). So logically, B for C and D, is a sort of their "base class", right? Or am I wrong?
You're correct.
I think that in this case the best solution is to try:
#include <iostream>
using namespace std;
class A {
public:
void print(){ cout << "print A" << endl; };
};
class B: public A {
public:
virtual void print(){ cout << "print B" << endl; };
};
class C: public B {
public:
void print(){ cout << "print C" << endl; };
};
int main()
{
A *a = new C();
B *b = new C();
a->print(); // will print 'print A'
b->print(); // will print 'print C'
return 1;
}
You are entirely correct. Child inherits what its ancestors have. Base classes can't inherit what the child has (such as a new function or variable). Virtual functions are simply functions that can be overridden by the child class if the that child class changes the implementation of the virtual function so that the base virtual function isn't called.
A is the base class for B,C,D. B is a the base class for C, D. and C is the base class for D too.
Of course you can do it. Virtual method is optional to override so it doesn't matter that you declare it in class A or B. If you dont want to use that method in class A then simply declare in in class B.
Related
here i have some code
class A{
private:
int a;
public:
void abc()
{ cout << a << endl; }
};
class B : public A
{ };
main() {
B obj;
obj.abc(); // it works but why? obj.abc is printing a which should not inherit to class B because it is private.
ok so derived class inherited a public function abc() from the base class and that function is trying to output a member variable a that is not a part of derived class because it is private in base class? So how does it do that. this code prints a... but how?
a is private to class A, but since function abc is defined in class A, abc can make use of a.
B can make use of abc because abc is public and B derives from A (publicly).
a would not be available to functions defined in B.
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).
1.In the main function below, why does d.foo(9.5) not select the Base::foo(double) method from the base class? Doesn't the derived class inherit that method?
2.What causes the compile error?
class Base {
public:
virtual void foo(int){
cout << "Base::foo(int)" << endl;
}
virtual void foo(double){
cout << "Base::foo(double)" << endl;
}
};
class Derived : public Base {
public:
virtual void foo(int){
cout << "Derived::foo(int)" << endl;
}
};
void main() {
Derived d;
Base b, *pb = &d;
d.foo(9); // selects Derived::foo(int)
d.foo(9.5); // selects Derived::foo(int)
pb->foo(9); // selects Derived::foo(int)
pb->foo(9.5); // selects Base::foo(double)
Derived * d;
d->foo(9); // compile error
}
The compilation error is because of two variables with the same name in main().
As to your problem with inherited functions not being called for an instance of your Derived (except via pointer to Base)
The standard describes the "hiding rule", which makes this happen. Essentially, member functions declared in derived classes hide inherited functions with the same name but different signature inherited from the base class. The hiding rule is independent of whether the inherited functions are virtual or not.
The common solution is to introduce all inherited functions from the base class with using Base::foo. For example,
class Base {
public:
virtual void foo(int){
cout << "Base::foo(int)" << endl;
}
virtual void foo(double){
cout << "Base::foo(double)" << endl;
}
};
class Derived : public Base {
public:
using Base::foo;
virtual void foo(int){
cout << "Derived::foo(int)" << endl;
}
};
Another solution is to remember to explicitly override all inherited versions of the function (implement the derived class version to simply call the base class version of each function). This works with older compilers that do not support a using directive like the above. The catch is that it is necessary to explicitly do this with every inherited overload, and it is easy to miss one.
In the main function below, why does d.foo(9.5) not select the Base::foo(double) method from the base class? Doesn't the derived class inherit that method?
Yes, but it's hidden by the function with the same name in the derived class. You can unhide it with a using-declaration in the derived class:
using Base::foo;
What causes the compile error?
You're trying to declare a second variable called d. Change the name to something that's not already used; and initialise it to point to a valid object, otherwise you'll have a runtime error or other undefined behaviour.
Derived * pd = &d;
pd->foo(9); // selects Derived::foo(int)
Also, main has the wrong return type. It must return int.
1) Because this is exactly how polymorphism work. If a virtual function is redefined in a derived class, this (and only this) redefined version will be called. If the function is not virtual it's vice versa: only the base class function will be called.
//Example 1: non-virtual function
class Base
{
public:
void foo()
{
std::cout << "Base";
}
}
class Derived : public Base
{
public:
void foo()
{
std::cout << "Derived";
}
}
Base * base = new Base();
base->foo()//prints "Base"
Base * derived = new Derived();
derived->foo()//prints "Base", since the function is not virtual, and the version from the base class is called
//Example 2: virtual function
class Base
{
public:
virtual void foo()
{
std::cout << "Base";
}
}
class Derived : public Base
{
public:
void foo()
{
std::cout << "Derived";
}
}
Base * base = new Base();
base->foo()//prints "Base"
Base * derived = new Derived();
derived->foo()//prints "Derived", since the function is virtual, and the redefined version from Derived class is called
2) The compile error happens because you have a conflicting declaration - two objects are called d.
Derived * d;
d->foo(9); // compile error
You don't have instantiated the object:
Derived * d = new Derived;
If you not create the object the compiler use the previous declaration of d: Derived d that is not a pointer.
Hello I am new to C++ and learning the conversion from a base class pointer to a derived class pointer.
class Base{
public:
virtual void method(){
std::cout << "this is a base class" << std::endl;
}
};
class Derived:public Base{
public:
virtual void method(){
std::cout << "this is a derived class" << std::endl;
}
};
int main(){
Base *a = new Base();
Derived *b = new Derived();
a = b
a->method()
Base c;
Derived d;
c=d;
c.method()
return 0;
}
a->method() will print "this is a derived class"
c.method() will print "this is a base class""
How to understand the different behavior? I kind of understand that a = b basically let the compiler know a is a Base class pointer pointing to Derived class, so the polymorphism will work here. But what does c=d do in the code?
I am using Xcode..
Thanks in advance!
The c = d line does what's called slicing - it takes the base part of d and copies it to c, slicing off all the properties of the derived class. This includes any virtual functions defined in the derived class.
If you want polymorphism, you must use a pointer or reference.
Consider the sample code below:
#include <iostream>
using namespace std;
class A
{
private:
static int a;
int b;
protected:
public:
A() : b(0) {}
void modify()
{
a++;
b++;
}
void display()
{
cout << a <<"\n";
cout << b <<"\n";
}
};
int A::a=0;
class B : public A {
private:
int b;
public:
B(): b(5)
{
}
};
int main()
{
A ob1;
B ob2;
ob1.display();
ob2.display();
return 0;
}
In the code above, the class A has a private data member band class B also has a private data member b. The function display() is used to display the data members.
When i invoke display() using ob1.display(), display() accesses the private data member b of class A. I understand that. But when i invoke display using ob2.display, which b does display() access? Is it the b of class A or b of class B? Kindly explain the why it accesses class A's b or class B's b
It will access A::b. The display method implementation in class A has no clue about the existence of B::b at all, let alone using it. For all intents and purposes, B::b is separate from A::b. Only in the scope of B itself, the name conflict makes b refer to B::b, hiding A::b. Member variables cannot be virtual.
ob2.display() will access the derived class member.
The member function call is always evaluated on this, this->display() the this in case points to object of your Base class and hence any reference to b inside the display() function is evaluated as this->b which is b of the Base class.
This is because display() of the Base class has no knowledge of whether any other class derives from it. Base class is always independent of the Derived class. To solve a problem the uual pattern followed is to provide a display() method in the Derived class which then in turn calls the dsiplay() method of the Base class.
void B::display()
{
//cout << a <<"\n";
cout << b <<"\n";
A::display();
}
It is class A. A::display() cannot access B private members.