分配给派生类和多态性的基类指针

Base Class Pointer Assigned to Derived Class and Polymorphism

本文关键字:基类 指针 多态性 派生 分配      更新时间:2023-10-16

对于下面的代码,当基类指针分配给派生类时,我对多态性有疑问。

当派生类的对象直接使用打印函数时,输出是显而易见的。

当我使用基类指针并指向派生类的对象时,将使用基类的打印函数,但输出是来自派生对象的信息。谁能详细解释为什么?谢谢!

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;
}
函数

print()不是virtual,因此不是多态的。基类上的函数隐藏了子类的函数。

要使代码按预期工作,您唯一需要做的就是在类Person中使print()虚拟

class Person {
public:
    Person() {};
    virtual ~Person() {};
    Person(string nm):name(nm) {};
    virtual void print() const;
private:
   string name;
};

请注意,我添加了一个虚拟析构函数,这是每个要继承的类所必需的。

输出显示派生对象的信息,因为子类继承基类的成员(即 name,设置为彼得、莎莉和爱德华)。

代码行为的关键词是"静态绑定和动态绑定"。

当编译器在编译时读取以下语句时,它看到 ptr3 是 Person 类型,它检查 person 类并将 print() 替换为 Person 类中定义的 print 函数地址。所有这些都发生在编译时,这就是称为静态绑定的原因。

ptr3->print();

为什么它能够打印通过派生类对象输入的信息?

在下面的语句中,您将调用基类的构造函数并在基类成员中输入信息。 PTR3* 属于基类类型,因此它有权访问其成员。

Employee(int num, int sal, string nm) : IDNumber(num), salary(sal), Person(nm) {};

如果,您赚取了 int 薪水;员工类中的公共成员并尝试通过以下方式访问

PTR3->工资

它会给出错误

PTR3 没有指定工资的成员

由于薪水是派生类的成员,基类对象无法访问它。