The thing is, when using value instead of pointer, you always get values of the same type. So for this case:
Base b;
The variable b
cannot be anything but an instance of b
. Even if you do that:
Derived d;
Base b = d; // d is sliced into b
The variables d
and b
are different instances. To do the assignement, the compiler must convert the value of d
into a value of type Base
, much like this:
double d = 9.5;
int i = d; // i is 9, it sliced the .5
So you must have some kind of reference, or some kind of variable that allows varying types.
Using a reference/pointer
This is usually how polymorphism is done. You make b
a reference type that can refer to any instance of object that extends Base
.
std::unique_ptr<Base> b = std::make_unique<Derived>();
This creates a unique pointer of type Derived
, and assign it to a unique pointer of type Base
. b
now points to the instance of a Derived
object.
If instead you want to use reference, you must have a variable that stays alive enough time to use it, something like that:
void foo(Base& refToBase);
void bar() {
Derived d;
foo(d);
} // d is guaranteed to die here.
Using a variant
A variant is a type that can have a value of multiple types. It can only contain one value, so it 'varies' between types.
For example:
std::variant<int, std::string> v;
v = 12;
v = "text";
So you can use that to create a variable that can vary between derived types:
std::variant<A, B> a_or_b;
if(...) {
a_or_b = A{};
} else {
a_or_b = B{};
}
std::visit(
[](Base& b) { /* do stuff with the base */ },
a_or_b
);