对于以下代码,当基类指针分配给派生类时,我对多态性有疑问。
当派生类的对象直接使用打印功能时,输出很明显。
当我使用基类指针并指向派生类的对象时,将使用基类的print函数,但输出是派生对象的信息。任何人都可以详细解释为什么?谢谢!
class Person {
public:
Person() {};
Person(string nm):name(nm) {};
void print() const;
private:
string name;
};
class Student : public Person {
public:
Student(int num, string nm) : IDNumber(num), Person(nm) {};
void print() const;
private:
int IDNumber;
}
class Employee : public Person {
public:
Employee(int num, int sal, string nm) : IDNumber(num), salary(sal), Person(nm) {};
void print() const;
private:
int IDNumber, salary;
}
void Person::print() const {
cout << name << endl;
}
void Student::print() const {
cout << "GoGoGo! ";
Person::print();
}
void Employee::print() const {
cout << "I work: ";
Person::print();
}
int main() {
Person per("Peter");
Student stu(3141, "Sally");
Employee emp(2718, 40, "Edward");
Person* ptr = &per;
Person* ptr2 = &stu;
Person* ptr3 = &emp;
per.print(); //Peter
stu.print(); //GoGoGo! Sally
emp.print(); //I work: Edward
ptr->print(); //Peter
ptr2->print(); //Sally
ptr3->print(); //Edward
return 0;
}
答案 0 :(得分:1)
函数print()
不是virtual
,因此不是多态的。基类上的函数隐藏了子类的功能。
要使代码按预期工作,您唯一要做的就是在课程print()
中设置Person
虚拟内容:
class Person {
public:
Person() {};
virtual ~Person() {};
Person(string nm):name(nm) {};
virtual void print() const;
private:
string name;
};
请注意,我添加了一个虚拟析构函数,这对于要继承的每个类都是必需的。
输出显示派生对象的信息,因为子类继承了基类的成员(例如,name
,设置为Peter,Sally和Edward)。
答案 1 :(得分:0)
代码行为的关键词是“静态绑定和动态绑定”。
当编译器在编译时读取以下语句时,会发现ptr3是Person类型的,它将检查person类并将print()替换为Person类中定义的print函数地址。所有这些都发生在编译时,这就是为什么称之为静态绑定。
mix.js('resources/js/Chart.min.js', 'public/js').version();
为什么能够打印通过派生类对象输入的信息?
在下面的语句中,您正在调用基类的构造函数,并在基类成员中输入信息。 ptr3 *是基类类型,因此它可以访问其成员。
ptr3->print();
如果,您支付的是国际薪金; Employee类中的公共成员,并尝试通过
访问ptr3->工资
它将给出错误
ptr3没有具名工资的成员
由于薪水是派生类的成员,并且基类对象无法对其进行访问。