多态性与虚函数

1.  函数重载(overloading)与静态联编(static binding)


函数重载(overloading)指的是,允许多个不同函数使用同一个函数名,但要求这些同名函数具有不同的参数表。

   . 参数表中的参数个数不同;

   . 参数表中对应的参数类型不同;

   . 参数表中不同类型参数的次序不同。 

      例:

 intabs(int n){

    return (n<0?-n:n);

  }

 

  floatabs(floatn)  {

    if (f<0) f=-f;

    return f;

  }

 

    系统对函数重载这种多态性的分辨与处理,是在编译阶段完成的 -- 静态联编(static binding)

函数超载(overriding)、虚函数(virtual function)及动态联编(dynamic binding)


(1) 函数超载(overriding)

 

   . 仅在基类与其派生类的范围内实现;

   . 允许多个不同函数使用完全相同的函数名、函数参数表以及函数返回类型;

       (2)虚函数(virtual function)

 

       . 在定义某一基类(或其派生类)时,若将其中的某一函数成员的属性说明为virtual,则称该函数为虚函数(virtual function)

       . 虚函数的使用与函数超载密切相关。若基类中某函数被说明为虚函数,则意味着其派生类中也要用到与该函数同名、同参数表、同返回类型、但函数(实现)体不同的这同一个所谓的超载函数。 

class graphelem {

protected:

  int color;

public:

  graphelem(int col) {

  color=col;

  }

  virtualvoid draw(){ ... };  

   //虚函数draw,每一个类都要draw出属于它的类对象图形

};


classline:publicgraphelem{

  public:

  virtual void draw(){ ... };  //虚函数draw,负责画出line

  ...

};

 

classcircle:publicgraphelem{

  public:

  virtual void draw(){ ... };  //虚函数draw,负责画出circle

  ...

};

classtriangle:publicgraphelem{

  public:

  virtual void draw(){ ... };  //虚函数draw,负责画出triangle

  ...

};

 

      (3)动态联编(dynamic binding)

 

       与虚函数以及程序中使用指向基类的指针(变量)密切相关。

     注意:C++规定,基类指针可以指向其派生类的对象(也即,可将派生类对象的地址赋给其基类指针变量),但反过来不可以。这一点正是函数超载及虚函数用法的基础。

      例1.建立上述类line、circle以及类triangle的类对象,而后调用它们各自的draw函数画出它们。

  

     方法1:直接通过类对象(由类对象可以唯一确定要调用哪一个类的draw函数)

 

   line ln1;  circle cir1;   triangle tri1;

   ln1.draw(); 

   cir1.draw(); 

   tri1.draw(); 

      方法2:使用指向基类的指针(动态联编,要靠执行程序时其基类指针的动态取值来确定调用哪一个类的draw函数)

 

   graphelem *pObj;

   line ln1;  circle cir1;  triangle tri1;

   pObj=&lin1;    pObj->draw();

   pObj=&cir1;    pObj->draw(); 

   pObj=&tri1;    pObj->draw();

      例2. 假设inte_algo为基类,其中说明了一个虚函数integrate,并在其三个派生类中,也说明了该虚函数integrate(使用不同方法计算定积分)。

 

     那么,可使用函数integrateFunc来实现调用不同虚函数integrate的目的:

 

void integrateFunc(inte_algo * p){  

  //基类指针p可指向任一派生类的对象

  p->integrate();   

  //调用的将是不同派生类的integrate函数

}

 

   主调函数处使用:

integrateFunc( <某派生类的类对象地址> ); 

      在编译阶段,系统无法确定究竟要调用哪一个派生类的integrate。此种情况下,将采用动态联编方式来处理:在运行阶段,通过p指针的当前值,去动态地确定对象所属类,而后找到对应虚函数。

  

 纯虚函数与抽象基类

 

     如果不准备在基类的虚函数中做任何事情,则可使用如下的格式将该虚函数说明成纯虚函数

           virtual<函数原型>=0;

        纯虚函数不能被直接调用,它只为其派生类的各虚函数规定了一个一致的原型规格(该虚函数的实现将在它的派生类中给出)。

 

     含有纯虚函数的基类称为抽象基类。注意,不可使用抽象基类来说明并创建它自己的对象,只有在创建其派生类对象时,才有抽象基类自身的实例伴随而生。

 

     实际上,抽象基类是其各派生类之共同点的一个抽象综合,通过它,再加上各派生类的特有成员以及对基类中那一纯虚函数的具体实现,方可构成一个具体的实用类型。

 

     另外:如果一个抽象基类的派生类中没有定义基类中的那一纯虚函数、而只是继承了基类之纯虚函数的话,则这个派生类还是一个抽象基类(其中仍包含着继承而来的那一个纯虚函数)。




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值