0

全部:

当我研究 C++ 中的多态性时,我在这里找到了一个小例子:

#include <iostream>
using namespace std;
class Base{
public:
virtual void f(float x){cout<<"Base::f(float)"<<x<<endl;}
        void g(float x){cout<<"Base::g(float)"<<x<<endl;}
        void h(float x){cout<<"Base::h(float)"<<x<<endl;}
};

class Derived:public Base{
public:
virtual void f(float x){cout<<"Derived::f(float)"<<x<<endl;}
        void g(int x){cout<<"Derived::g(int)"<<x<<endl;}
        void h(float x){cout<<"Derived::h(float)"<<x<<endl;}
};
int main(void){
  Derived d;
  Base *pb=&d;
  Derived *pd=&d;

  //Good:behavior depends solely on type of the object
  pb->f(3.14f);     //Derived::f(float)3.14
  pd->f(3.14f);     //Derived::f(float)3.14

  //Bad:behavior depends on type of the pointer
  pb->g(3.14f);     //Base::g(float)3.14
  pd->g(3.14f);     //Derived::g(int)3(surprise!)

  //Bad:behavior depends on type of the pointer
  pb->h(3.14f);     //Base::h(float)3.14(surprise!)
  pd->h(3.14f);     //Derived::h(float)3.14


  return 0;
}

在学习了虚函数之后,我想我明白了多态是如何工作的,但是这段代码中仍然存在一些问题,我不想打扰别人解释这段代码是如何工作的,我只需要一个可以向我展示 Derived 内部细节的人类(不需要太多细节,只显示Vtable中的方法函数指针(或索引)以及那些不是虚拟继承的结构)。

从 pb->h(3.14f); //Base::h(float)3.14(surprise!) 我想应该有几个 vtable,对吗?

谢谢!

4

1 回答 1

2

您的代码中只有一个多态 ( virtual) 成员函数签名:f(float). 其他三个函数 、g(float)g(int)不是h(float)虚函数。由于您的“(惊喜!)”评论是在调用g()and之后h(),我猜您要么对这些函数不是多态的感到惊讶,要么实际上对非多态函数的行为感到惊讶。

如果您对此感到惊讶g()并且h()不是多态的,请意识到它virtual位于每个多态函数之前。如果一个函数没有被声明virtual,它只会是多态的,如果它与基类中的虚函数具有相同的签名(这也意味着你的virtualinDerived是多余的,但我个人认为这种多余的使用virtual是好的风格) . 由于virtualonly 出现在 之前f(float), onlyf(float)将是多态的。

由于h()不是多态的,因此h()通过基指针调用调用h().

关于,派生类中的名称隐藏基类中的任何相应名称,除非通过声明g()带回。using这就是为什么pd->g(3.14f)调用Derived::g(int)即使Base::g(float)是更好的匹配。 Base::g不可见。如果你把using Base::g;类派生,它会调用浮动版本g()。(请注意,这里virtual没有区别g(),因为g(int)g(float)是不同的函数签名——没有办法覆盖另一个。)

高温高压

于 2013-04-26T19:22:27.480 回答