我跟随的文字说:
使用对象调用虚函数始终是静态解析的。 仅通过指针或引用获得动态分辨率。
现在考虑以下计划:
#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
在这里,我通过对象实例调用基类和派生类对象,通过指针调用 not 。但似乎该功能正在动态解决。文字错了吗?如果不是这意味着什么?
答案 0 :(得分: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
。