代码之家  ›  专栏  ›  技术社区  ›  juztcode

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

  •  1
  • juztcode  · 技术社区  · 7 年前

    我下面的文字是这样写的:

    使用对象调用虚函数总是静态解析的。你 只有 通过指针或引用获取动态分辨率。

    现在考虑以下计划:

    #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();
    }   
    

    输出:

    Three args box ran
    Three args box ran
    Mainclass usable volume is: 24000
    Mainclass usable volume is: 20400
    

    这里,我通过基类和派生类对象的对象实例和 通过指针。但该函数似乎正在动态解析。文本是否有误?如果不是,那是什么意思?

    1 回复  |  直到 7 年前
        1
  •  5
  •   aschepler    7 年前

    “使用对象对虚拟函数的调用总是静态解析。只能通过指针或引用获得动态解析。”

    这句话与其说是描述C++语言的规则,不如说是编译器可以采用的快捷方式。

    您正在呼叫 showFunction 直接在对象的名称上。所以假设 showFunction公司 已声明为虚拟。编译器知道调用的对象的确切类型 first second :它们不可能是其他类型的对象。因此,尽管语言说任何重写函数都必须由 first.showVolume() second.showVolume() ,除了编译器可以立即找到的函数外,不可能得到任何其他函数,因此实际上不需要编写任何代码来确定在生成的程序中调用哪个函数。正确的功能 Mainclass::showVolume() (或 Derivedclass::showVolume() ,如果存在的话),可以直接调用,这样效率会稍微高一些。

    该报价不适用于 Volume() 在…内 showVolume() 自从 Volume 命名非静态成员, 卷() 表示与相同 this->Volume() this 是一个指针,它可能指向完整类型与类型匹配的对象,也可能不指向该对象 Mainclass* const 指针的。因此,在这种情况下,编译器需要进行动态解析,以确定要调用哪个函数。

    但还有一件事需要注意:的确,您只能通过指针或引用获得动态分辨率,但您不是这样的 总是 通过指针或引用获取动态分辨率。将函数命名为“限定id”时 :: 标记,该语言表示调用的函数是静态确定的,重写被忽略。例如,如果您的代码 showVolume() 更改为使用 Mainclass::Volume() this->Mainclass::Volume() ,你会发现它从不呼叫 Derivedclass::Volume