欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++中虚函数实现父类函数多态性

程序员文章站 2022-04-22 08:22:43
...

今天项目用到了策略设计模式,其中需要实现子类函数的多态性,先总结复习一下。
一、小例子
话不多说,先上例程。

#include <iostream>

using namespace std;

class Mouse{
public:
  /**
   * 虚函数 带有实现
   */
  virtual void click(){
    cout<<"Mouse is clicked!"<<endl;
  };
  /*
   * 纯虚函数 表明Mouse为抽象类
   */
  virtual void print()=0; 
};


class OpticalMouse : public  Mouse{
  /**
   * 未重写虚函数
   */
  virtual void click();
  /**
   * 实现纯虚函数
   */
  virtual void print(){
    cout<<"This is an OpticalMouse."<<endl;
  };
};

class  MechanicalMouse : public  Mouse{
  /**
   * 未重写虚函数
   */
  virtual void click();
  /**
   * 实现纯虚函数
   */
  virtual void print(){
    cout<<"This is a mechanical Mouse."<<endl;
  };
};


int main(int argc, char **argv) {
    
   Mouse* myMouse;
   myMouse = new OpticalMouse;
   myMouse->click();
   myMouse->print();
    return 0;
}

编译时会报错 如下图所示:


C++中虚函数实现父类函数多态性
Screenshot from 2018-05-04 17-36-25.png

错误为: “undefined reference to ‘vtable for ×××’”,这个问题主要是由于子类调用了父类的虚函数,在子类中没有定义导致的虚拟函数表出现未定义错误。将程序修改如下:

class OpticalMouse : public  Mouse{
  /**
   * 未重写虚函数
   */
  virtual void click(){
cout<<"Optical Mouse is clicked."<<endl;
};
  /**
   * 实现纯虚函数
   */
  virtual void print(){
    cout<<"This is an OpticalMouse."<<endl;
  };
};

重新运行,得到结果:
Starting: /home/xxdk/projects/virDemo/build/virdemo
Optical Mouse is clicked.
This is an OpticalMouse.
*** Exited normally ***
说明用父类的指针可以完成子类虚函数的调用,从而实现运行时多态。

二、虚函数的机制
虚函数是一种动态绑定机制,其中有两个主要概念:vtable和vptr。
具体过程为:每一个内含虚拟函数的类,编译器都会为它做出一个虚拟函数的表vtable,表中的元素指向一个虚拟函数的地址。编译器会为类别加上个成员变量,是一个指向该虚拟函数表的指针vptr。
子类会继承基础类别的虚拟函数表,如上例所示,如果对于虚拟函数子类有同名的虚拟函数的话,就会覆盖原父类的虚拟函数地址,从而达到通过指向父类的指针调用了子类的虚拟函数的功能,从而实现多态。但是如果子类的虚拟函数没有实现的话就会出现上面说的undefined reference to ‘vtable for ××ב的错误。

三、虚函数的使用
如上所述,为了使程序能够实现多态的功能,应该在子类中实现父类的虚函数。为了更显式地达到这个效果,在父类中应使用纯虚函数来完成。即令虚函数=0,这样在子类中必须实现所有纯虚函数才能使类实例化,而用指向父类的指针则可以顺利地使用子类的函数,从而达到多态化的效果。