c++虚函数、多态性与虚表

多态

多态性就是指同样的消息被类的不同的对象接收时导致的完全不同的行为的一种现象。这里所说的消息即对类成员函数的调用。多态实质是一个函数名称的多种形态

C++支持两种不同类型的多态:一种是编译时的多态,另一种是运行时的多态。在编译时的多态是通过静态联编实现的;而在运行时的多态则是通过动态联编实现的。

函数联编:对一个函数的调用,在编译或运行时确定将其连接到相应的函数体的代码,实质是把一个标示名与一个存储地址联系在一起的过程。

在程序中可以把一个公有派生类对象当作其基类对象来处理,一个公有派生类的对象提供了基类对象的所有行为。

虚函数

C++中的动态联编是通过虚函数实现的,虚函数必须存在于继承的环境下。一个派生类用基类的指针标示,派生类和基类中有相同的函数名。如果将这个函数声明为虚函数,则用基类的指针调用这个函数,会表现出派生类的特征

class 类名

{……

 virtual 类型 函数名(参数表);

 ……

};

当一个类的成员函数说明为虚函数后,就可以在该类的(直接或间接)派生类中定义与其基类虚函数原型相同的函数。这时,当用基类指针指向这些派生类对象时,系统会自动用派生类中的同名函数来代替基类中的虚函数。也就是说,当用基类指针指向不同派生类对象时,系统会在程序运行中根据所指向对象的不同,自动选择适当的函数,从而实现了运行时的多态性。


虚函数可以在一个或多个派生类中被重新定义,因此,属于函数重载的情况,但这种重载与一般的函数重载是不同的,要求在派生类中重新定义时,必须与基类中的函数原型完全相同,包括函数名、返回类型、参数个数和参数类型的顺序。这时无论在派生类的相应成员函数前是否加上关键字virtual,都将视其为虚函数,如果函数原型不同,只是函数名相同,C++将视其为一般的函数重载,而不是虚函数。只有类的成员函数才能声明为虚函数,全局函数及静态成员函数不能声明为虚函数。

#include <iostream>
using namespace std;
 
class Base
{ 
      public: 
      virtual void show() { cout<<"base class \n"; }   
};
 
class Der1: public Base
{ 
      public:
      void show() { cout<<"derived class 1 \n"; }   
};
 
class Der2: public Base
{ 
      public: 
      void show() { cout<<"derived class 2 \n"; }  
};
 
int main()
{  
    Base bobj;
    Base *p;
    Der1 dobj1;
    Der2 dobj2;
    p=&bobj; 
    p->show();
    p=&dobj1;
    p->show();
    p=&dobj2;
    p->show();
    system("pause");
    return 0;
 }

output:

base class

derived class 1

derived class 2

纯虚函数

纯虚函数是在基类中只声明虚函数而不给出具体的函数定义体,将它的具体定义放在各派生类中,称此虚函数为纯虚函数.通过该基类的指针或引用就可以调用所有派生类的虚函数,基类只是用于继承,仅作为一个接口,具体功能在派生类中实现.

纯虚函数的声明如下:(注:要放在基类的定义体中)

   virtual 函数原型=0;

声明了纯虚函数的类,称为抽象类。

  • 抽象类中可以有多个纯虚函数

  • 不能声明抽象类的对象,但可以声明指向抽象类的指针变量和引用变量

  • 抽象类也可以定义其他非纯虚函数

  • 如果派生类中没有重新定义基类中的纯虚函数,则在派生类中必须再将该虚函数声明为纯虚函数

  • 从抽象类可以派生出具体或抽象类,但不能从具体类派生出抽象类

  • 在一个复杂的类继承结构中,越上层的类抽象程度越高,有时甚至无法给出某些成员函数的实现,显然,抽象类是一种特殊的类,它一般处于类继承结构的较外层

  • 引入抽象类的目的,主要是为了能将相关类组织在一个类继承结构中,并通过抽象类来为这些相关类提供统一的操作接口

#include <iostream>
using namespace std;
 
class Shape
{ 
   protected:
      double x,y;
   public:
      void set(double i, double j) { x=i; y=j;  }
      virtual void area()=0;    //声明纯虚函数  
};
 
class Triangle: public Shape
{ 
      public:
        void area() {cout<< "三角形面积: " <<0.5*x*y<<endl;}  
};
 
class Rectangle: public Shape
{ public:
        void area(){ cout<<"矩形面积:" <<x*y<<endl; }  
};
 
int main()
  { 
     Shape *p;
     Triangle t;
     Rectangle r;
     p=&t;
     p->set(5.1,10);
     p->area();   
     p=&r;
     p->set(5.1,10);
     p->area();
     system("pause");  
     return 0;
}

output

三角形面积: 25.5

矩形面积:51




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值