Reputation: 129
I have code something like that:
class Person
{
public:
Person(const std::string& name, std::size_t age);
virtual void print() const;
void inc_age() { ++_age; }
private:
std::string _name;
std::size_t _age;
};
class Employee : public Person
{
public:
Employee(const std::string& name, std::size_t age, double salary);
virtual void print() const override;
void add_bonus(double percent);
private:
double _salary;
};
main is:
int main()
{
Person mike{"Mike"s, 20};
Employee manager{"Sam"s, 35, 100};
Person* p{&manager};
if (p) p->print(); // this line
std::cout << '\n';
return 0;
}
It's obvious now that I got it wrong, but as I realise line in main
with comment
should use Person::print()
because of implicit upcasting. But even using staic_cast<Person*>(p)->print()
invoke Employee::print()
.
It's just academic interest (I'm a CS student) but how to make it use Person::print()
without slicing (is slicing UB?)?
Another question is that: Our professor has said that if class isn't polymorphic (has no virtual functions) dynamic_cast
happily runs without any error, silently producing UB. Is it correct and is there a way to prevent this?
P.S. Sorry for my poor English and poor knowledge of C++. I'm learning both quite some time but haven't become proficient in either yet.
Upvotes: 1
Views: 73
Reputation: 22354
The whole point of virtual
functions is that you call the most derived class function even if you only have pointer to base class. If you want to call base class function directly, you have to spell it out:
manager.Person::print()
or
p->Person::print()
is slicing UB?
No, it's perfectly well defined. But the behaviour of slicing may be unexpected if you don't know about it, and I can't think of any situation where you actually want to invoke it.
Our professor has said that if class isn't polymorphic (has no virtual functions) dynamic_cast happily runs without any error, silently producing UB
True if you want to downcast (cast a Base
pointer/reference to Derived
pointer/reference), however, upcasting (from Derived
to Base
) is perfectly fine for any types (and can be done by static_cast
as well or implicitly as you have done in your code).
Upvotes: 3