C++中的静态和动态分辨率

juz*_*ode 1 c++ oop polymorphism

我正在关注的文字说:

使用对象调用虚函数始终是静态解析的.您只能通过指针或引用获得动态分辨率.

现在考虑以下程序:

#include <iostream>

class Mainclass{
    protected: 
        double length{1.0};
        double width{1.0};
        double height{1.0};

    public:
        Mainclass(double lv, double wv, double hv):length{lv}, width{wv}, height{hv}{
            std::cout<<"Three args box ran"<<std::endl;
        }

        void showVolume() const{
            std::cout<<"Mainclass usable volume is: "<<Volume()<<std::endl;
        }

        virtual double Volume() const{
            return length*width*height;
        }

};


class Derivedclass: public Mainclass{
    public: 
        Derivedclass(double lv, double wv, double hv): Mainclass{lv, wv, hv}{}

        double Volume() const{
            return 0.85*length*width*height;
        }

};

int main(){
    Mainclass first{20.0, 30.0, 40.0};
    Derivedclass second {20.0, 30.0, 40.0};

    first.showVolume();
    second.showVolume();
}   
Run Code Online (Sandbox Code Playgroud)

输出:

Three args box ran
Three args box ran
Mainclass usable volume is: 24000
Mainclass usable volume is: 20400
Run Code Online (Sandbox Code Playgroud)

在这里,我通过对象实例而不是通过指针调用基类和派生类对象.但似乎该功能正在动态解决.文字错了吗?如果不是这意味着什么?

asc*_*ler 5

"使用对象调用虚函数总是静态解析.只能通过指针或引用获得动态分辨率."

这句话并不是描述C++语言的规则,而是允许编译器采用的快捷方式.

showFunction直接调用对象的名称.所以假设showFunction被宣布为虚拟.编译器知道被调用对象的确切类型,first并且second:它们实际上不可能是其他类型的对象.所以,虽然语言说,任何超越功能必须通过调用first.showVolume()second.showVolume(),有没有可能的方式,结果会比那些编译器可以立即找到其它任何功能,所以它实际上并不需要把所有的代码来确定哪个函数打电话给结果程序.可以直接调用正确的函数Mainclass::showVolume()(或者Derivedclass::showVolume(),如果它存在),这可以稍微更高效.

引用不适用于Volume()内部的召唤showVolume().由于Volume名称是非静态成员,Volume()意味着相同this->Volume(). this是一个指针,它可能指向或不指向完整类型与Mainclass* const指针类型匹配的对象.因此,在这种情况下,编译器需要进行动态解析以确定要调用的函数.

但还有一点需要注意:确实你只能通过指针或引用获得动态分辨率,但是你总是通过指针或引用得到动态分辨率.当使用::令牌将函数命名为"限定id"时,语言表示调用的函数是静态确定的,并且忽略覆盖.例如,如果您的代码showVolume()更改为使用Mainclass::Volume()this->Mainclass::Volume(),您将看到它从不调用Derivedclass::Volume.