understanding the base-to-derive conversion - c++

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.

Related

dynamic_cast fails when cast a base class to derived class

I have two classes, base class and a derived class.
The base class has a virtual method.
Here is my test example:
class Base
{
public:
virtual void Hello() { cout << "-> Hello Base" << endl; }
};
class Derived: public Base
{
public:
void Hello() { cout << "-> Hello Derived" << endl; }
};
int main()
{
Base *mBase = new Base;
// something to do
....
Derived *mDerived = dynamic_cast<Derived*>(mBase);
mDerived->Hello();
return 0;
}
I'm looking to use the Hello() method of the class derived after the cast of mBase to mDerived.
But the problem is that when I try to use dynamic_cast it will crash the application, if not if I use reinterpret_cast the Hello() method of the Base class will be called.
Result in the case dynamic_cast:
Segmentation fault (core dumped)
Result in the case dynamic_cast:
-> Hello Base
dynamic_cast fails when cast a base class to derived class
This is what is supposed to happen. When you dynamic cast a pointer to an object whose dynamic type is not the casted type, then you get a null pointer as the result.
In your example, you indirect through the null pointer and attempt to call a member function which results in undefined behaviour.
When using dynamic cast, you must always check whether you got null or not.
if I use reinterpret_cast...
Then the behaviour will still be undefined because you'll be indirecting through a pointer to an object that does not exist. Unless you create an instance of the derived class, you cannot call its non static member function.
You can convert a base instance into a derived one like this for example:
Base b;
Derived d = b;
What happens is that the base sub object of the derived instance is copy initialised from b.
Two problems in your code: Base should have a virtual destructor so Dervied isntances can be properly destructed via a pointer to Base. Then, you are not constructing an object of type Derived, so the cast cannot succeed. dynamic_cast can fail and you should check its result for not being a nullptr. Also you forgot to delete the created object.
If you do create an instance of type Derived your code works:
#include <iostream>
using std::cout;
using std::endl;
class Base
{
public:
virtual void Hello() { cout << "-> Hello Base" << endl; }
virtual ~Base(){}
};
class Derived: public Base
{
public:
void Hello() { cout << "-> Hello Derived" << endl; }
};
int main()
{
Base* mBase = new Derived;
Derived *mDerived = dynamic_cast<Derived*>(mBase);
if (mDerived) mDerived->Hello();
delete mBase;
}

concept of base, derive class and use them properly

you have to use the concept of base, derive class and use them properly. while doing it, I'm faced with some problems.
Can you help me solve the issues ?
My Code :
#include <iostream>
class Base {
public:
Base (int data) : _data(data){}
virtual void printData(){
std::cout << "Base" << _data << std::endl;
}
private:
int _data;
};
class Derived : public Base {
public:
Derived(derivdata) : Base(derivdata){}
void printData(){
cout << "Derived " << _data << endl;
}
}
int main(){
Derived *var = new Derived(5);
var-> printData();
Base* basevar = static_cast<Base>(*var);
basevar-> printData();
}
Base* basevar = static_cast<Base>(*var); is wrong,
it would be Base* basevar = static_cast<Base*>(var);
but Base* basevar = var; is sufficient.
and version without memory leak:
int main(){
Derived derived(5);
derived.printData(); // "Derived 5\n"
Base& base = *derived;
base.printData(); // "Derived 5\n" as method is virtual
}
There are several problems here, that could be typos:
a missing semicolon after the class Derived
in the constructor Derived(derivdata) : Base(derivdata){} the type of derivdata is missing. (there is no default int in c++)
you are missing the namespace std:: before cout and endl in Derived::printData
in Derived::printData the member _data is not accessible, because it is private to Base (You could make it protected or write a getter for it)
The core problem is this cast: Base* basevar = static_cast<Base>(*var); This will actually dereference the value of var, then try to cast this value to Base, and afterwards tries to assign the result (of type Base) to a variable of type Base*.
For polymorphic casting you can use dynamic_cast: Base* basevar = dynamic_cast<Base*>(var);
But don't expect basevar->printData(); to print "Base", since the pointer is still pointing to an instance of Derived and the method is declared virtual.
To access a method of the base class you need to explicitly tell the compiler to do so:
basevar->Base::printData();(prints "Base5")

Accessing virtual base class function from a derived class

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.

Virtual function inheritance

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.

converting pointer to base object into pointer of derivate class

I've been confused by the converting a pointer to base class object into pointer of derivate class.
Please check the following code:
derivate_class *d1 = (derivate_class*)cb;
d1->print();
d1->print1();
The result is:
I'm a virtual function in base.
I'm a function in derivate class.
Can anyone help me explain why d1->print() print "I'm a virtual function in base."?
#include <iostream>
using namespace std;
class base
{
public:
virtual void print()
{
cout << "I'm a virtual function in base." << endl;
}
};
class derivate_class : public base
{
public:
void print()
{
cout << "I rewrite the virtual function in base." << endl;
}
void print1()
{
cout << "I'm a function in derivate class." << endl;
}
};
int main()
{
base* b = new base();
derivate_class *d = new derivate_class();
b->print();
d->print1();
base* cb = b;
b = d;
b->print();
cout << "*********************" << endl;
derivate_class *d1 = (derivate_class*)cb;
d1->print();
d1->print1();
system("pause");
return 0;
}
It's UB, so anything can happen.
But here's an explanation: d1 doesn't actually point to a derivate_class, but to a base.
base* b = new base();
//...
base* cb = b;
derivate_class *d1 = (derivate_class*)cb;
d1->print();
d1->print1();
The call is resolved dynamically because it's through a pointer and the method is virtual.
print1 isn't virtual so the call is resolved statically. print however is virtual, so the implementation in the most derived type is called. But the most derived type is actually base in this case.
Under the hood, the method print is looked for in the virtual function table that the vfptr in cb points to. Since cv is a base, the table will be that of base, which contains the function print with the base::print implementation. That's why that's the function getting called.
d1 is a derivate_class pointer but the data it's actually pointing to (cb) is of type base. Since print() is virtual, the call is resolved dynamically and so it will find base's implementation in the virtual function table instead of derivate_class's.