C/C++虚函数与虚继承

2017-01-05 20:04:42来源:CSDN作者:dongxianfei人点击

第七城市

之前一篇博文我们分析了C++和Java在继承多态方面的一些简单比较C/C++继承类的多态表现,当时我们说到在多态的情况下我们访问的都是父类的行为,那怎样才能访问到子类的函数呢?答案是通过定义虚函数来实现,那今天我们就写一个Demo来看一下。

虚函数

//测试虚函数class Animal {public:    char name[128];    char behavior[128];    //父类的outPut方法设置为虚函数    virtual void outPut() {        cout << "Animal" << endl;    }    void outPutAnimal() {        cout << "Father" << endl;    }    Animal() {        strcpy(name, "Animal");        strcpy(behavior, "Call");    }    virtual ~Animal(){    }};class Dog: public Animal {public:    char name[128];    char sex;    //重写的方法也是虚函数    void outPut() {        cout << "Dog" << endl;    }    void outPutDog() {        cout << "Son" << endl;    }    Dog() {        strcpy(name, "Dog");        sex = 'M';    }};

我们来看一下结果

//测试代码Animal *dog = new Dog;//多态行为cout << dog->name << endl;cout << dog->behavior << endl;dog->outPut();dog->outPutAnimal();//测试结果AnimalCallDog//此刻这里表现的是子类的行为,如果不是虚函数将表现为父类行为Father

好啦到此虚函数我们就通过一个示例简单的分析了一下,但是虚函数在使用的过程中有以下几个方面的限制。

  1. 只有类的成员函数才能是虚函数
  2. 静态成员函数不能是虚函数
  3. 内联函数不能是虚函数
  4. 构造函数不能是虚函数,析构函数通常是虚函数

虚继承

我们先来看一个没有虚继承的示例

//普通多继承class CAnimal                               //定义一个动物类{public:    CAnimal()                                   {        cout << "动物类被构造" << endl;               }    void Move()                     {        cout << "动物能够移动" << endl;               }};class CBird: public CAnimal                //从CAnimal类继承CBird类{public:    CBird()                             {        cout << "鸟类被构造" << endl;            }    void FlyInSky()                         {        cout << "鸟能够在天空飞翔" << endl;             }    void Breath()                           {        cout << "鸟能够呼吸" << endl;            }};class CFish: public CAnimal                //从CAnimal类继承CFish{public:    CFish()                         {        cout << "鱼类被构造" << endl;            }    void SwimInWater()                      {        cout << "鱼能够在水里游" << endl;          }    void Breath()                           {        cout << "鱼能够呼吸" << endl;            }};class CWaterBird: public CBird, public CFish    //从CBird和CFish类派生子类CWaterBird{public:    CWaterBird()                                {        cout << "水鸟类被构造" << endl;               }    void Action()                               {        cout << "水鸟即能飞又能游" << endl;     }};

这是一个多继承的问题,我们在这里没有使用虚继承,看一下其执行结果。

//测试代码CWaterBird waterBird;waterBird.FlyInSky();waterBird.SwimInWater();waterBird.Action();//waterBird.Breath()无法直接访问Breath(),存在二义性waterBird.CBird::Breath();//需指定类名来访问waterBird.CBird::Move();//存在两个Animal类,所以应该指定类名waterBird.CFish::Breath();//运行结果//CAnimal类被构造两次动物类被构造鸟类被构造动物类被构造鱼类被构造水鸟类被构造鸟能够在天空飞翔鱼能够在水里游水鸟即能飞又能游鸟能够呼吸动物能够移动鱼能够呼吸

由于CBird和CFish均派生自同一个父类CAnimal,而二者派生子类CWaterBird时将存在两个CAnimal类的复制,如果想只有一个CAnimal类那在此就需使用虚继承了,我们在来看一下虚继承的示例。

//虚拟多继承class CAnimal                               //定义一个动物类{public:    CAnimal()                               {        cout << "动物类被构造" << endl;               }    void Move()                         {        cout << "动物能够移动" << endl;           }};class CBird: virtual public CAnimal         //从CAnimal类虚继承CBird类{public:    CBird()                             {        cout << "鸟类被构造" << endl;                    }    void FlyInSky()                         {        cout << "鸟能够在天空飞翔" << endl;         }    void Breath()                           {        cout << "鸟能够呼吸" << endl;            }};class CFish: virtual public CAnimal         //从CAnimal类虚继承CFish{public:    CFish()                             {        cout << "鱼类被构造" << endl;                }    void SwimInWater()                      {        cout << "鱼能够在水里游" << endl;          }    void Breath()                           {        cout << "鱼能够呼吸" << endl;            }};class CWaterBird: public CBird, public CFish    //从CBird和CFish类派生子类CWaterBird{public:    CWaterBird()                        {        cout << "水鸟类被构造" << endl;               }    void Action()                               {        cout << "水鸟即能飞又能游" << endl;             }};

这里使用了虚继承,我们来看一下运行结果。

//测试代码CWaterBird waterBird;waterBird.FlyInSky();waterBird.SwimInWater();waterBird.Action();waterBird.Move();//可以直接访问Move(),此时只有一个Animal类waterBird.CBird::Breath();//Breath()由于两个父类都存在,所以还是需要指定父类waterBird.CFish::Breath();//测试结果//Animal类被构造一次动物类被构造鸟类被构造鱼类被构造水鸟类被构造鸟能够在天空飞翔鱼能够在水里游水鸟即能飞又能游动物能够移动鸟能够呼吸鱼能够呼吸

好啦,今天我们对虚函数和虚继承就简单的分析到这里了,其实平时在开发过程中我们应该尽量少用多继承,因为多继承会带来很多麻烦的情况,所以能用单继承就使用单继承。

第七城市

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台