虚拟方法和静态/动态定位

Virtual methods and static/dynamic alocation

本文关键字:动态 定位 静态 方法 虚拟      更新时间:2023-10-16

我想知道为什么在这个例子中静态对象调用父方法而动态对象调用子方法。

#include <string>
#include <iostream>
using namespace std;
class Father {
public:
    virtual string Info() {
        return "I am father";
    }
};
class Son : public Father {
public:
    string Info() {
        return "I am son";
    }
};
int main() {
    Father f = Son();
    cout << f.Info(); // I am father
    Father* pf = new Son();
    cout << pf->Info(); // I am son
    return 0;
}

这是由于切片-您的f实际上是一个自动定位的Father,分配Father f = Son()实际上是Father f = Father(Son()),因此f的动态类型实际上是Father,并且正如预期的那样,Father::Info()将被调用。

关于切片的更多信息可以在这篇文章中找到

因为Father f = Son()创建了Father类型的对象,并从对象Son复制属性(在这种情况下没有要复制的属性),所以Father * pf = new Son()接收到指向对象Son的指针,它实际上可能是任何Father派生的对象。

最后,在您的示例中,您有3个对象。复制到Father fFather funnamed object Son(),以及指向Son类型对象的Father * pf

这就是多态性。当你像这样静态地分配一个对象时:
Son son();

在编译时,您知道son的类型是Son。如果动态分配,则可以选择将Son对象存储在Son指针或Father指针中。如果将它们存储在Son指针中,则与上面相同。但是,如果将Son对象存储在Father类型指针中:

Father* ptr = new Son()

那么编译器无法知道Father指针指向的是哪种类型的对象。因此在运行时,当它发现时,它会调用合适版本的Info