浅谈C++多态

浅谈C++多态

动态、静态联编

静态联编

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

普通成员函数重载可表达为两种形式:

  1. 在一个类说明中重载

  2. 基类的成员函数在派生类重载。有 3 种编译区分方法:

    (1)根据参数的特征加以区分

    (2)使用“ :: ”加以区分

    (3)根据类对象加以区分

类指针的关系

1.基类指针可以获取派生类对象地址,却只能访问派生类从基类继承的成员!

使用基类指针引用派生类对象会调用从基类继承的成员函数,若派生类中有函数和基类中重名,则不会调用派生类的函数。

2.派生类指针只有经过强制类型转换之后,才能引用基类对象 。

使用基类指针引用派s生类对象、派生类指针引用基类对象

方法:
①若使用指针,必须强制类型转换 使得指针类型发生变化

((要强制转换的类型 *)基类指针 )->调用的函数

​ ②不用指针,通过对象调用函数

//使用基类指针引用派生类对象
#include<iostream>
#include<cstring>
using namespace std;
class A{
protected:
    char name[20];
public:
     void get(char *n){
        strcpy(name,n);
     }
     void p(){
     cout<<"A::name :"<<name<<endl;
     }
} ;
class B:public A{
    char ph[12];
public:
     void get(char *n){
        strcpy(ph,n);
     }
     void show_phone(){
     cout<<"B::phone : "<<ph<<endl;
     }

};
int main(){
    A *p; //基类指针
    A aa;
    p=&aa;   //引用基类对象
    p->get("aaa");
    p->p();

    B bb;
    p=&bb;     //引用派生类对象
    ( ( B * ) p ) -> get("110"); //还可以直接调用bb对象完成传值  bb.get()
    ( ( B * ) p ) -> show_phone();  //强制类型转换,使指针指向派生类
    return 0;
}
//派生类指针引用基类对象 
//要调用基类函数,必须使用强制类型转换
#include<iostream>
#include<cstring>
using namespace std;
class DATE{
protected:
    int year,month,day;
public:
    DATE(int y,int m,int d){
    setdate(y,m,d);
    }
    ~DATE(){}
    void setdate(int y,int m,int d){
    year=y;
    month=m;
    day=d;
    }
    void print(){
     cout<<"现在时间为:"<<year<<"年"<<month<<"月"<<day<<"日";
     }
};
class DateTime : public DATE{
private:
    int hour,minn,sec;
public:
    DateTime(int y,int m,int d,int hh,int mm,int ss):DATE(y,m,d){
    gettime(hh,mm,ss);
    }
    ~DateTime(){}
    void gettime(int hh,int mm,int ss){
        hour=hh;
        minn=mm;
        sec=ss;
    }
    void print(){
    //在此处打出日期和时间
     ((DATE *)this)->print();  
        //强制类型转换使得指针指向基类对象——与 DATE::print()等效!
    cout<<hour<<"时"<<minn<<"分"<<sec<<"秒"<<endl;}
};
int main(){
    DATE dd(2021,5,16);
    DateTime dt(2021,5,16,10,45,45);
    DateTime *p;  //派生类指针
    p=&dt;
    p->print(); //指针指向派生类对象
    return 0 ;
}

虚函数和动态联编

虚函数

冠以关键字 virtual 的成员函数称为虚函数。

虚函数必须是类的成员函数,在派生类层面相同的重载函数都保持虚特性

在派生类中重载基类的虚函数要求函数名、返回类型、参数个数、参数类型和顺序完全相同!

如果仅仅返回类型不同,C++认为是错误重载

如果函数原型不同,仅函数名相同,丢失虚特性

析构函数可以是虚函数构造函数不能是虚函数!

不能将友元说明为虚函数,但虚函数可以是另一个类的友元。

基类有虚函数,派生类继承了函数——虚继承

实现虚继承,应具备两点:

①类与类之间具备继承关系

②具有虚函数 (冠以关键字 virtual 的成员函数)

实现运行时多态的方法

①有基类、派生类 (存在继承关系

说明虚函数

用基类指针调用派生类的不同实现版本

为了实现基类指针的灵活调用,将要灵活使用的函数设为虚函数,以使得this指针根据虚特性作类型转换执行不同实现版本 。

//基类指针在运行时,调用不同版本的成员函数
#include<iostream>
using namespace std ;
class  Base
{
public :
    Base(char xx)  { x = xx; }
    virtual void who(){ cout << "Base class: " << x << "\n" ; }
//以关键字 virtual 声明虚函数 以使基类指针可以调用同形函数 (派生类中的 virtual 可省略)
protected:
       char x;
} ;
class  First_d : public  Base
{
public :
    First_d(char xx, char yy):Base(xx)  { y = yy; }
    virtual void who(){ cout << "First class: "<< x << ", " << y << "\n" ; }
protected:
    char y;
} ;
class  Second_d : public  First_d
{
public :
    Second_d( char xx, char yy, char zz ) : First_d( xx, yy ) { z = zz; }
    virtual void who() { cout << "Second class: "<< x << ", " << y << ", " << z << "\n" ; }
protected:
    char z;
} ;
int main(){
    Base bb('x');
    First_d fd('a','b');
    Second_d sd('c','d','e');
    Base *p;
    p=&bb; p->who();
    p=&fd; p->who();
    p=&sd; p->who();
    return 0;
}

虚析构函数

虚析构函数可指引 delete 运算符正确析构动态对象

普通析构函数在删除动态派生类对象时,会使得派生类中继承基类的部分内存资源无法回收,使用虚析构函数即可解决这个问题.

方法:在原有析构函数前加关键字 virtual

设计类层次结构时,提供一个虚析构函数,能够使派生类对象在不同状态下正确调用析构函数

动态联编

程序联编推迟到运行时进行,所以又称为晚期联编。switch 语句和 if 语句是动态联编的例子。

纯虚函数和抽象类

1.纯虚函数是一个在基类中说明的虚函数,在基类中没有定义,其功能无法实现。

纯虚函数为各派生类提供一个公共界面.一个具有纯虚函数的基类称为抽象类

说明形式:

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

【要使抽象类变为非抽象类,需要在派生类中将基类中的纯虚函数的功能实现

​ 若不对抽象类的功能进行实现,编译将不通过!

2.含有纯虚函数的类称为基类称为“抽象类”

不能建立抽象类型存储空间

①抽象类不能建立对象(无法进行内存分配)

②可以声明抽象类的指针

③可以声明抽象类的引用(因为引用不分配内存)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值