Consider a Base
class and a derived class that inherits from it called Child
.
Assume the Base
class has a member function declared virtual
, and that Child
overrides that function.
I would like to declare a variable as a Base
class object, initialize it using the Child
derived class constructor, and then use the Child
class version of the member function.
In other words, the following C++ program:
#include <iostream>
class Base {
public:
virtual int give_number(int x) { return x; }
};
class Child : public Base {
public:
int give_number(int x) { return x+1; }
};
int main() {
Base base;
Child child;
Base child2;
child2 = Child();
std::cout << "Base says " << base.give_number(1) << "\n";
std::cout << "Child says " << child.give_number(1) << "\n";
std::cout << "Child2 says " << child2.give_number(1) << "\n";
}
results in the following output:
Base says 1
Child says 2
Child2 says 1
But I would instead prefer the following output:
Base says 1
Child says 2
Child2 says 2
Is there a way to accomplish this?
In the statement:
child2 = Child();
You are slicing the Child
object, which is why the Child::give_number()
method is not being called. child2
is a Base
instance, never a Child
instance. During the assignment, only the Base
portion of the new Child
object is copied into child2
.
You must use a pointer or reference when calling a virtual method polymorphically, eg:
#include <iostream>
class Base {
public:
virtual ~Base() = default;
virtual int give_number(int x) { return x; }
};
class Child : public Base {
public:
int give_number(int x) override { return x+1; }
};
int main() {
Base base;
Child child;
Child child2;
Base& base2 = child2;
std::cout << "Base says " << base.give_number(1) << "\n";
std::cout << "Child says " << child.give_number(1) << "\n";
std::cout << "Base2 says " << base2.give_number(1) << "\n";
}
Or:
#include <iostream>
class Base {
public:
virtual ~Base() = default;
virtual int give_number(int x) { return x; }
};
class Child : public Base {
public:
int give_number(int x) override { return x+1; }
};
int main() {
Base base;
Child child;
Child child2;
Base* base2 = &child2;
std::cout << "Base says " << base.give_number(1) << "\n";
std::cout << "Child says " << child.give_number(1) << "\n";
std::cout << "Base2 says " << base2->give_number(1) << "\n";
}
Or:
#include <iostream>
#include <memory>
class Base {
public:
virtual ~Base() = default;
virtual int give_number(int x) { return x; }
};
class Child : public Base {
public:
int give_number(int x) override { return x+1; }
};
int main() {
Base base;
Child child;
//Base* child2 = new Child;
std::unique_ptr<Base> child2 = std::make_unique<Child>();
std::cout << "Base says " << base.give_number(1) << "\n";
std::cout << "Child says " << child.give_number(1) << "\n";
std::cout << "Child2 says " << child2->give_number(1) << "\n";
//delete child2;
}