我正在学习多态性,我对此情况感到困惑: 假设我有以下C ++类:
class A{
...
virtual void Foo(){
Boo();
}
virtual void Boo(){...}
}
class B : public A{
...
void Foo(){
A::Foo();
}
void Boo(){...}
}
我创建一个B实例并调用它的Foo()函数。当该函数调用A :: Foo()时,使用的Boo()方法是A类还是B类?谢谢!
答案 0 :(得分:9)
除非您使用类限定函数调用,否则所有方法调用都将被视为相等,即动态分派(如果是虚拟),静态分派(如果不是虚拟)。当您使用类名完全限定时,您调用的方法实际上是禁用动态调度机制并引入直接方法调用。
class A{
virtual void Foo(){
Boo(); // will call the final overrider
A::Boo(); // will call A::Boo, regardless of the dynamic type
}
virtual void Boo();
};
class B : public A{
void Foo(){
//Foo(); // Would call the final overrider
// (in this case B: infinite recursion)
A::Foo(); // Will call A::Foo, even if the object is B
}
void Boo();
};
隐式this
指针不是此处讨论的重要部分,因为使用显式对象进行调用时会发生完全相同的情况:
B b;
b.Foo(); // will call B::Foo -- note 1
b.A::Foo(); // will call A::Foo
注1:在这个例子中,编译器可以忽略动态调度机制,因为它知道实例的具体类型(它看到定义并且它不是引用/指针)但是你可以想象如果发生同样的情况会发生b
是一个引用,或者相当于它是一个指针->
而不是.
答案 1 :(得分:2)
由于Boo()
是虚拟的,因此调用派生类'覆盖。
Boo();
只是this->Boo();
的简写,您可以在其中看到通过指针调用虚拟函数。 (this
在A* const
中的类型为Foo()
。)通过引用或指针调用的虚函数将始终在最派生类中调用覆盖(从构造函数调用时除外)或析构函数)。
答案 2 :(得分:1)
在A里面,
virtual void Foo(){
Boo();
}
被转换为this->Boo()
;因为Boo在A中被声明为虚拟,所以派生类的方法Boo被调用。尽量不要将Boo声称为A中的虚拟实验 - 您会看到A-> Boo()被调用。
Arpan