继承类结构是什么样的?

时间:2013-04-26 19:03:10

标签: c++

所有

当我在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!) 我想应该有几个vtables,我是对的吗?

谢谢!

1 个答案:

答案 0 :(得分:2)

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

如果您对g()h()不具有多态性感到惊讶,请认识到virtual位于每个多态函数之前。如果函数未声明virtual,则只有与基类中的虚函数具有相同的签名时,它才是多态的(这也意味着virtual中的Derived是多余的,但我个人觉得virtual这种多余的使用是好的风格。由于virtual仅出现在f(float)之前,因此只有f(float)会是多态的。

由于h()不是多态的,因此通过基指针调用h()调用h()的基本版本并不奇怪。

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

HTH