c++__虚函数与多态

简述

  • 多态性(Polymorphism)是指一个名字,多种语义;或界面相同,多种实现。
  • 重载函数是多态性的一种简单形式。
  • 虚函数允许函数与函数体的联系再运行是菜进行,称为动态联编。

多态的实现

  • 多态性的实现和联编这一概念有关。所谓联编(Binding,绑定)就是把函数名与函数体的程序代码连接(联系)在一起的过程。
  • 联编分成两大类:静态联编和动态联编。
  • 静态联编优点:调用速度快,效率高,但缺乏灵活性;动态联编优点:运行效率低,但增强了程序灵活性。
  • C++为了兼容C语言仍然是编译型的,采用静态联编。为了实现多态性,利用虚函数机制,可部分地采用动态联编。
  • 多态从实现的角度来讲可以划分为两类:编译时的多态和运行时的多态。
  • 编译时的多态是通过静态联编来实现的。静态联编就是在编译阶段完成的联编。编译时多态性主要是通过函数重载和运算符重载实现的。
  • 运行时的多态是用动态联编实现的。动态联编是运行阶段完成的联编。运行时多态性主要是通过虚函数来实现的。

静态联编

静态联编,是程序的匹配、连接在编译阶段实现,也称为早期匹配。
重载函数使用静态联编。

普通成员函数重载课表达为两中国形式:
1.在一个类说明中重载
2.基类的成员函数在派生类重载。有三种编译区分方法:
(1).根据参数的特征加以区分
(2).使用“::”加以区分
(3).根据类对象加以区分
例如:

Aobj.Show()调用A::Show()

类指针的关系

基类指针和派生类指针与基类对象和派生类对象4种可能匹配:

  1. 直接用基类指针引用基类对象;
  2. 直接用派生类指针引用派生类对象;
  3. 用基类指针引用一个派生类对象;
  4. 用派生类指针引用一个基类对象。
    例:
A    * p ;		// 指向类型 A 的对象的指针
A    A_obj ;	// 类型 A 的对象
B    B_obj ;	// 类型 B 的对象
p = & A_obj ;	// p 指向类型 A  的对象
p = & B_obj ;	// p 指向类型 B  的对象,它是 A 的派生类

派生类指针引用基类对象

#include<iostream>
#include<cstring>
using namespace std ;
class  A_class
{      char name[20] ;
    public :    void  put_name( char * s ) { strcpy_s( name, s ) ; }
                    void  show_name() { cout << name << "\n" ; }
};
class  B_class  : public  A_class
{      char phone_num[ 20 ] ;
    public :    void  put_phone( char * num )  { strcpy_s ( phone_num , num ) ; }
                    void  show_phone()  { cout << phone_num << "\n" ; }
};
int main()
{ A_class  * A_p ;      A_class  A_obj ;
   B_class   B_obj ;  
   A_p = & A_obj ;     
   A_p -> put_name( "Wang xiao hua" ) ;   A_p -> show_name() ;  
   A_p = & B_obj ;
   A_p -> put_name( "Chen ming" ) ;     A_p -> show_name() ; 
   B_obj.put_phone ( "5555_12345678" );
   ( ( B_class * ) A_p ) -> show_phone() ;
}

虚函数和动态联编

冠以关键字 virtual 的成员函数称为虚函数
实现运行时多态的关键首先是要说明虚函数,另外,必须用基类指针调用派生类的不同实现版本
基类指针虽然获取派生类对象地址,却只能访问派生类从基类继承的成员

#include<iostream>
using namespace std ;
class  Base
{ public : Base(char xx)  { x = xx; }
               void who()  { cout << "Base class: " << x << "\n" ; }
   protected: char x;
} ;
class  First_d : public  Base
{ public :  First_d(char xx, char yy):Base(xx)  { y = yy; }
               void who()  { cout << "First derived class: "<< x << ", " << y << "\n" ; }
   protected: char y;
} ;

注意

  • 一个虚函数,在派生类层界面相同的重载函数都保持虚特性
  • 虚函数必须是类的成员函数
  • 不能将友元说明为虚函数,但虚函数可以是另一个类的友元
  • 析构函数可以是虚函数,但构造函数不能是虚函数
    虚函数的析构
    例如:
#include<iostream>
using namespace std ;
class A
 { public:
        ~A(){ cout << "A::~A() is called.\n" ; }
 } ;
class B : public A
 { public:
        ~B(){ cout << "B::~B() is called.\n" ; }
} ;
int main()
 { A *Ap = new B ;	
    B *Bp2 = new B ;
    cout << "delete first object:\n" ;
    delete Ap;
    cout << "delete second object:\n" ;
    delete Bp2 ;
} 

纯虚函数和抽象类

  • 纯虚函数是一种特殊的虚函数;
  • 在许多情况下,在及雷暴中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。
class  point { /*……*/ } ;
class  shape// 抽象类
{ point  center ;
      ……
  public :
  point  where ( ) { return  center ; }
  void  move ( point p ) {center = p ; draw ( ) ; }
  virtual  void  rotate ( int ) = 0 ; 		// 纯虚函数
  virtual  void  draw ( ) = 0 ;			// 纯虚函数
} ;

纯虚函数和抽象类

#include<iostream>
using namespace std ;
class Number
{ public :      Number (int i) { val = i ; }
                    virtual void Show() = 0 ;
  protected:  int val ;
};
class Hex_type : public Number
{ public:    Hex_type(int i) : Number(i) { }
             void Show()  { cout << "Hexadecimal:" << hex << val << endl ; }
};
class Dec_type : public Number
{ public:    Dec_type(int i) : Number(i) { }
             void Show()  { cout << "Decimal: " << dec << val << endl ; }
};
class Oct_type : public Number
{ public:    Oct_type(int i) : Number(i) { }
             void Show()  { cout << "Octal: " << oct << val << endl ; }
}; 
void fun( Number & n )	// 抽象类的引用参数
{  n.Show() ; } 
int main()
{ Dec_type n1(50);
   fun(n1);		// Dec_type::Show()
   Hex_type n2(50);
   fun(n2);		// Hex_type::Show()
  Oct_type n3(50);
   fun(n3);		// Oct_type::Show()
} 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值