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

虚函数与多态

程序员文章站 2022-07-15 16:50:50
...

    C++的多态性包括:

(1)编译时多态(静态多态):函数重载、运算符重载、模板实现

(2)运行时多态(动态多态):虚函数实现

    虚函数的概念:

    在某基类中声明为virtual并在一个或多个派生类中被重新定义的成员函数。用法格式:virtual 函数返回类型 函数名 (参数表) {函数体} 。作用为通过指向派生类的基类指针或引用来操作对象。

    Inheritance(继承)with virtual function(虚函数)

(1)non-virtual函数:你不希望derived class重新定义(override,覆写)它。

(2)virtual函数:你希望derived class重新定义(override,覆写)它,且你对它已有默认定义。

(3)pure virtual函数:你希望derived class一定要重新定义(override,覆写)它,你对它没有默认定义。在基类中实现纯虚函数的方法是在函数原型后面加“= 0”

通过下面的程序来认识一下这三种函数:

class Shape
{
public:
  virtual void draw() const = 0; //纯虚函数
  virtual void error(const std::string& msg); //虚函数
  int objectID() const; //非虚函数
  ...
};

class Rectangle:public Shape{...}; //继承
class Ellipse:public Shape{...}; //继承

     下面来看一个简单的例子:

using namespace std;

class A
{
public:
  A(){};
  ~A(){};
  void showMe()
  {
    cout << "A" << endl;
  }
};

class B : class A
{
public:
  B(){};
  ~B(){};
  void showMe()
  {
    cout << "B" <<endl;
  }
};

int main(int argc, char const* argv[])
{
  A *p1 = new A;
  A *p2 = new B;
  p1 -> showMe();
  p2 -> showMe();
  
  return 0;
}

    该段程序运行的结果是“A”“A”。问题是p2明明指向的是class B的对象,可是调用的却是class A的showMe()函数,这是我们不希望得到的结果。解决这个问题就需要用到虚函数。

using namespace std;

class A
{
public:
  A(){};
  ~A(){};
  virtual void showMe()
  {
    cout << "A" << endl;
  }
};

class B : class A
{
public:
  B(){};
  ~B(){};
  virtual void showMe()
  {
    cout << "B" <<endl;
  }
};

int main(int argc, char const* argv[])
{
  A *p1 = new A;
  A *p2 = new B;
  p1 -> showMe();
  p2 -> showMe();
  
  return 0;
}

    此时再运行,输出的结果为“A”“B”。加上virtual关键字后,基类的成员函数showMe()变成虚函数,自然地派生类的showMe()也自动变成虚函数。对于派生类的响应函数前是否需要加virtual关键字,则都可以。

    总结一下就是:当基类指针指向一个子类对象,通过这个指针调用子类中和基类同名的函数时,如果基类中声明为虚函数(子类不写也可以)就会调用子类的这个函数(覆写的概念),如果基类中没有声明为虚函数就会调用基类的函数。

    


相关标签: 虚函数 继承