ProMike
ProMike

Reputation: 129

Why upcasted variable use virtual function from derived class C++

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

Answers (1)

Yksisarvinen
Yksisarvinen

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

Related Questions