What's wrong with the code?
You're invoking Undefined Behavior here:
Foo* bar = &Bar();
This code actually shouldn't compile, but at least two compilers accept it (the Microsoft Visual Studio compiler, and the Intel C++ compiler).
This executes the following steps:
- Create a temporary instance of Bar
- Take the address of that instance
- Assign the address to the variable
bar
- Destroy that instance
When, on the next line, you try to use bar
, the temporary instance has already been destroyed. This invokes the undefined behavior.
How do we fix the Undefined Behavior?
What you're missing is a new
:
// Old way; prone to memory leaks
Foo* bar = new Bar();
Even better, use a unique_ptr
:
// New way; bar acts like a pointer, and it gets automatically deleted
// at the end of the scope
std::unique_ptr<Foo> bar = std::make_unique<Bar>();
This will allow you to use bar
safely:
std::cout << "name=" << bar->name << " number = " << bar->number << '\n';
Why is it printing "foo default value"
instead of "here I want other value"
?
Variables aren't virtual. That means that if you use bar->name
, because bar
is a pointer to Foo
, this refers to name
as it's defined in Foo
.
In order to fix this, we need to use virtual member functions:
struct Foo {
virtual std::string getName() {
return "I am foo.";
}
// We need to have this, so that the destructor is called correctly.
virtual ~Foo() = default;
};
struct Bar {
std::string getName() override {
return "I am actually bar.";
}
};
Now, things work as intended:
std::unique_ptr<Foo> bar = std::make_unique<Bar>()
std::cout << bar->getName() << '\n'; //Prints "I am actually bar."
When, on the next line, you try to use bar
, the temporary instance has already been destroyed. This invokes the undefined behavior.
Instead you should do:
std::unique_ptr<Foo> bar (new Bar());