C++ virtual function: Base class function is called instead of derived - c++

I have following code snippet:
class base
{
public:
virtual void print(char a){ std::cout << " Base\n"; }
};
class derived : public base
{
public:
void print(float a) { std::cout << " Derived\n"; }
};
int main() {
base* d = new derived;
d->print(1.5);
}
Output is Base.
Why is the output coming from the base function and not from the derived one?

You have not overridden the function in the base class, you have overloaded it: The version in the derived class takes a float as an argument, and is quite a different beast from the base class method which takes a char. Moreover, the float version in the derived class shadows the base class version: The base class version becomes inaccessible for calls on the derived type.
As such, the following code
Derived d;
d.print('a');
d.print(1.5);
will print
Derived
Derived
because the call is resolved by the compiler to the only version of print() that's available in Derived.
Likewise, when you call d->print(1.5) through a pointer to Base, the derived class' version is inaccessible to the call: The compiler looks at the base class, sees that there is no print() method defined with a float argument, and converts the argument to char instead. It then calls the only implementation of print(char), which happens to be supplied by the base class.
If you simply change the signature of the print() method in the derived class to match that of the base class, the odd behavior will go away.

When you declare Base* d = new Derived;, the type of the class is Base, as printed by typeid(d).name(), so this instance doesn't have access to child class methods. If you change the type to Derived, you'll call the child method:
#include <iostream>
#include <typeinfo>
class Base
{
public:
virtual void print(char a) {
std::cout << " Base " << std::endl;
}
};
class Derived : public Base
{
public:
void print(float a) {
std::cout << " Derived " << std::endl;
}
};
int main()
{
Derived* d = new Derived;
std::cout << "class type is: " << typeid(d).name() << std::endl;
d->print(1.5);
return 0;
}
Output:
class type is: P7Derived
Derived
Furthermore, declaring the parent class print method virtual doesn't allow an instance of Base to call the child version of print because the child hasn't overridden it (different headers). Creating an instance of Base with Base *d = new Derived; and changing the Derived print method header to void print(char a) in the Derived class would allow you to call the child print method and output Derived, even from an instance of Base, using the virtual keyword.
#include <iostream>
#include <typeinfo>
class Base
{
public:
virtual void print(char a) {
std::cout << " Base " << std::endl;
}
};
class Derived : public Base
{
public:
void print(char a) {
std::cout << " Derived " << std::endl;
}
};
int main()
{
Base* d = new Derived;
std::cout << "class type is: " << typeid(d).name() << std::endl;
d->print(1.5);
return 0;
}
Output:
class type is: P4Base
Derived

Related

Copy constructing from a derived object

In the following code, the function foo is copy constructing a Base object c from a Derived object d. My question is: are we getting an exact copy? Because I'm not getting the polymorphic behavior I'm expecting
#include<iostream>
class Base
{
public:
virtual void sayHello()
{
std::cout << "Hello Base" << std::endl ;
}
};
class Derived: public Base
{
public:
void sayHello() override
{
std::cout << "Hello Derived" << std::endl ;
}
};
void foo(Base* d)
{
Base* c = new Base(*d);
c->sayHello() ;
}
int main()
{
Derived d;
foo(&d) ; //outputs Hello Base
}
There is no virtual constructor nor copy constructor.
However, it is possible to define a function that behaves like one.
In my case, it is the virtual member function copy() which I added to OP's sample:
#include <iostream>
class Base
{
public:
virtual Base* copy() const { return new Base(*this); }
virtual void sayHello()
{
std::cout << "Hello Base" << std::endl ;
}
};
class Derived: public Base
{
public:
virtual Base* copy() const override { return new Derived(*this); }
void sayHello() override
{
std::cout << "Hello Derived" << std::endl ;
}
};
void foo(Base* d)
{
Base* c = d->copy();
c->sayHello() ;
}
int main()
{
Derived d;
foo(&d) ; //outputs Hello Derived
return 0;
}
Output:
Hello Derived
Live Demo on coliru
The drawback is that every derived class of Base has to provide it to make it function properly. (I've no idea how to convince the compiler to check this for me with any trick.)
A partial solution could be to make copy() pure virtual in the class Base (assuming it is not meant to be instantiable).
you may wonna change the line of new
Base* c = new Derived(*d);
so you have the type Derived in a Base pointer. During runtime it is looked up, which type it is and you get the right output.
let me know if im wrong... just created this out of my mind on the fly.
To answer your question about whether or not this is copy constructing lets add some members. Base will have a member, m_b and Derived will inherit m_b but also have another member m_d
#include <iostream>
struct Base {
const int m_b;
Base() = delete;
Base(const int a_b) : m_b(a_b) {}
virtual void sayHello() {
std::cout << "Base " << m_b << std::endl;
}
};
struct Derived : public Base {
const int m_d;
Derived() = delete;
Derived(const int a_b, const int a_d) : Base(a_b), m_d(a_d) {}
void sayHello() override {
std::cout << "Derived " << m_b << ' ' << m_d << std::endl;
}
};
void foo(Derived* a) {
Base* b = new Base(*a);
b->sayHello(); // Output is "Base 1", 1 was copied from argument a
}
void bar(Derived* a) {
Base* d = new Derived(*a);
d->sayHello(); // Output is "Derived 1 2"
}
int main() {
Derived d(1, 2);
foo(&d);
bar(&d);
return 0;
}
The line:
Base* b = new Base(*a);
Created a Base and so sayHello calls Base's implementation which doesn't know about m_d. However this line does copy m_b from the derived class
The line:
Base* d = new Derived(*a);
Created a Derived and so sayHello calls Derived's implementation which copied both m_b and m_d
Expected polymorphic behavior will come into existence when the Base class pointer points to Derived class object. Then at run time the actual type of object pointed to by the Base class pointer will be checked and appropriate function will get called.
Base* c = new Base(*d); // <<-- case of object slicing
Here, c points to Base class object. Therefore, c->sayHello() ; is bound to call the Base::sayHello() at runtime.
are we getting an exact copy?. No since you are creating a Base object due to new Base. Due to object slicing the Base part of the *d object is passed to copy c'tor and what you get is corresponding Base object.
Base *c = new Derived(*d); will give the expected behavior.

Initialize an object with a different class

I saw this example:
http://www.cplusplus.com/doc/tutorial/typecasting/#dynamic_cast
(...)
class Base { virtual void dummy() {} };
class Derived: public Base { int a; };
(...)
Base * pba = new Derived;
Base * pbb = new Base;
(...)
Why 'pba' is a Base object if it's being initialized with Derived? Why not make it a Derived object?
Derived * pba = new Derived; // use this instead
And is it just a C++ thing?
neither pba nor pbb is an object but they are pointers of type base class Base so in your code you used he pointers polymorphically which means a base pointer can point to the same class or to its derived class object.
the object is created with new not pbb or pba themselves, consider this example:
#include <string>
#include <iostream>
using namespace std;
class Base
{
public:
virtual void Print() const { cout << "Base print()" << endl;} // virtual function
void Greet()const {cout << "in Base Say: hello!" << endl;}
};
class Derived : public Base
{
public:
void Print() const { cout << "Derived print()" << endl;} // ovrode the base member pritn()
void Greet()const {cout << "in Derived Say: hello!" << endl;}
};
int main()
{
Base* pba = new Derived;
pba->Print(); // Derived print()
pba->Greet(); // in Base Say: hello! ??? because Greet() is not virtual
Base* pbb = new Base;
pbb->Print(); // Base print()
pbb->Greet(); // in Base Say: hello!
return 0;
}
so at runtime the pointer pba and pbb can be assigned an object of Base or Derived classes thus the virtual member function are called accordingly.

Passing derrived classes as virtual base class without loss of changes

I have 1 base class and a couple of derrived classes that are pretty identic to the base. They look kind of like that:
class Base
{
protected:
data stuff;
size_t length;
public:
Base();
~Base();
virtual void print()
{
std::cout << "Base" << std::endl;
}
// Some more virtual functions
};
class Der1: public Base
{
public:
void print()
{
std::cout << "Der1" << std::endl;
Base::print();
}
};
class Der2: public Base
{
public:
void print()
{
std::cout << "Der2" << std::endl;
Base::print();
}
};
This example is kind of stupid, but what I want to say is that derived classes don't really affect the data itself - only 1 method that does something before actually printing data.
The problem I have is that I have some functions that get Base class as a parameter and does something with the data. The problem is - I can pass derived classes to those functions, but they are passes as Base class - so they lose their overloaded print, and if printed from inside of such function - it won't print any "Der1" or "Der2" strings to stdout.
Edit: They are passed as (const Base &source)
So my question is - what is a way to properly pass derived classes to such functions?
It looks like your functions get Base class as the parameter by value. If you use passing by reference instead - so function(Base& object) instead of function(Base object) - nothing will be lost.
In addition to previous answer, please see below your example:
#include <iostream>
class Base
{protected:
int stuff;
size_t length;
public:
Base(){};
~Base(){};
virtual void print()
{std::cout << "Base" << std::endl;}
// Some more virtual functions
};
class Der1: public Base
{public:
Der1(){};
~Der1(){};
void print()
{
std::cout << "Der1" << std::endl;
Base::print();
};
};
class Der2: public Base
{public:
void print()
{
std::cout << "Der2" << std::endl;
Base::print();
};
};
void function(Base& base)
{
base.print();
}
int main(void)
{
Der1 derived;
function(derived);
return 0;
}
Execution:
Der1
Base

Pointing to base, converted to Derived Pointer

Is it possible to get a base's derived class's type name by using typeid( TYPE ).name() ?
Example of pushing a base pointer back into a derived pointer, statically.
#include <iostream>
#include <typeinfo>
class base
{
public:
virtual void known() = 0;
};
class derived: public base
{
public:
void known() { std::cout << " I guess this means "; }
void unknown(){ known(); std::cout << " its possible "; }
};
int main()
{
derived d;
std::cout << typeid( d ).name() << std::endl;
// Prints out being a pointer to a derived class
base* b = &d;
std::cout << typeid( b ).name() << std::endl;
// Prints out being a pointer to a base class
// But how would you use it, or in any other way,
//get the original derived type name
derived * db = (derived*) b;
// db is casted at at compile time, the derived class is known
db->unknown();
}
Given an expression whose type is a polymorphic base class, The result of the typeid operator refers to a std::type_info object representing the type of the most derived object.
Example:
#include <iostream>
#include <typeinfo>
class Base {
public:
virtual ~Base() {}
}; // Base
class Derived : public Base {};
int main() {
Derived derived;
/* By reference. */ {
Base &base = derived;
std::cout << typeid(base).name() << std::endl;
}
/* By pointer. */ {
Base *base = &derived;
std::cout << typeid(*base).name() << std::endl;
// NOTE: typeid(base).name() results in printing of the Base class' name.
}
}
Both cases above print the Derived class' name.
References
N3797: 5.2.8 Type identification.
cppreference: 2) a)

C++ class member with same name as in base class

How does the this pointer behaves when used inside a base class method:
class Base{
public:
int a;
Base() : a(5) {}
void func(){
std::cout << " value is : " << this->a << std::endl;
}
};
class Derived : public Base{
private:
int a;
public:
Derived() : a(1){}
void func1(){
std::cout << " value is : " << this->a << std::endl;
}
};
int main(){
Derived d;
d.func();
d.func1();
}
the output of the code is :
value is : 5
value is : 1
As i am using the same object to call both the functions. So will the value of this pointer differ in methods for base and derived class ?
this->a is equivalent to a in that context, so it has nothing to do with the base pointer.
The member a is resolved statically, and the derived class hides the base class member, since they're both named a.
To check the this pointer itself, you can print it directly:
std::cout << this;
It will be the same for both objects.
The main thing to take from this is that Base::a and Derived::a are different. Try the following in Derived:
void func1(){
std::cout << "derived value is : " << a << std::endl;
std::cout << " base value is : " << Base::a << std::endl;
}
You would have to do this->Base::a to access Base's a. Else you always access Derived::a.
this pointer will always point to current object in which it exists.
When func is called, Base class is used and base class field is printed. but,
When func1 is called, Derived class is used and it's field is printed.
Try commenting this line Derived() : a(1){} and you'll get more clarity.