我有类似的代码:
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;
};
主要是:
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;
}
现在很明显我弄错了,但当我意识到在
main
中添加注释时
由于隐式向上转换,应该使用 Person::print()
。但即使使用 staic_cast<Person*>(p)->print()
也会调用 Employee::print()
。
只是学术兴趣(我是CS学生)但是如何让它使用Person::print()
而不进行切片(是切片UB?)?
另一个问题是:我们的教授说过,如果类不是多态的(没有虚函数)
dynamic_cast
会愉快地运行而没有任何错误,默默地产生UB。这是正确的吗?有办法防止这种情况发生吗?
附注抱歉我的英语很差,C++ 知识也很差。我已经学习了很长一段时间,但还没有变得精通。
virtual
函数的全部要点是,即使您有基类函数,您也可以调用最派生的类函数。如果你想直接调用基类函数,你必须拼写出来:
manager.Person::print()
或
p->Person::print()
我们的教授说过,如果类不是多态的(没有虚函数),dynamic_cast 会愉快地运行而没有任何错误,默默地产生 UB
如果您想向下转换(将
Base
指针/引用转换为 Derived
指针/引用),则为 True,但是,向上转换(从 Derived
到 Base
)对于任何类型都非常适合(并且可以通过以下方式完成)也static_cast
)。