C++学习笔记(三)多态性

目录

1多态性概述

2.运算符重载

2.1运算符重载为成员函数

2.2运算符重载为非成员函数

3.虚函数

4.纯虚函数、抽象类

5.虚析构函数

6 函数模板

6.1 函数模板定义格式:

6.2 函数模板的使用

7 类模板


1多态性概述

面向对象程序设计中,提供的“一个接口,多种方法”,即使用者发送一般信息,对象能够自动选择相应的处理。

1.1根据多态的实现方式分为:

(1)重载多态:普通函数重载、成员函数重载、运算符重载(三者本质上都是函数重载)

(2)包含多态:以虚函数为基础实现的多态

(3)参数多态:用类型参数实例化所体现的多态(模板)

1.2 根据多态的实现时间分为:

(1)编译时的多态:又称为静态多态;

如:函数重载、运算符重载

(2)运行时的多态:又称为多态多态

基于虚函数的包含多态;

2.运算符重载

运算符是C++系统内部定义的,她具有特定的语法规则。

2.1运算符重载为成员函数

在类中使用关键字operator声明(定义)一个特殊的函数。

格式:

函数返回值类型  operator 运算符(参数表)

在内体外实现该函数和普通成员函数类似要说明定义域:

格式:

函数返回值类型 类名::operator 运算符(参数表)

{

函数体,重实现该运算符的功能

}

例子:

2.2运算符重载为非成员函数

为了访问类的私有成员、公有成员,通常把运算符重载为友元函数。和一般友元函数类似,差别就在于“友元函数名”改为了“operator 运算符”。

在类体中声明格式:friend 函数返回值类型 operator 运算符(参数表)

3.虚函数

在存在继承关系的基类和派生类中,只要在基类定义了函数为虚函数,若派生类中有和基类虚函数完全相同的函数(返回值类型,参数个数、类型和顺序都相同,否则为重载),此时,定义一个基类指针,若指针指向基类对象,调用函数就会调用基类的;若指针指向派生类,调用函数就会调用派生类的。

格式:class 基类名

{

    virtual  返回值类型  函数名(参数表)

}

4.纯虚函数、抽象类

当基类的虚函数具体功能不明确,需要在派生类具体实现时,就可以定义为纯虚函数。

格式:

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

如果一个类包含了纯虚函数,那么称为抽象类。

5.虚析构函数

当一个类用来作基类时,往往把基类的析构函数定义为虚函数,在定义基类指针new一个派生类对象时,delete 指针时让析构函数能够自下而上执行析构函数,避免“内存泄露”。

例子

#include <iostream>

using namespace std;

class A

{public:

    int a;

    A(int a1)

    {a=a1;

    cout<<"A has been"<<endl;}

    virtual ~A(){cout<<"A xingou"<<endl;}//定义基类A析构函数为虚函数

};

class B:public A

{public:

    int b;

    B(int a1,int b1):A(a1)

    {b=b1;

    cout<<"B has been"<<endl;}

    ~B(){cout<<"B xingou"<<endl;}

};

class C:public B

{public:

    int c;

    C(int a1,int b2,int c1):B(a1,b2)

    {

        c=c1;

        cout<<"C has been"<<endl;

    }

    ~C(){cout<<"C xingou"<<endl;}

};

int main(int argc, char *argv[])

{

    QCoreApplication a(argc, argv);

    C obj_c(10,20,30);

    cout<<endl<<obj_c.a<<" "<<obj_c.b<<'\0'<<obj_c.c<<endl;

    A *obj_a=new C(1,2,3);

    delete obj_a;

return 0;

}

运行结果(左图):            若不定义基类A析构函数为虚函数运行结果(右图):

                

可见若不定义基类A析构函数为虚函数,在撤销动态存储空间时只调用了基类的析构函数,而不会执行派生类的析构函数,会导致内存泄漏。

6 函数模板

模板是C++多态的重要实现方式之一。有函数模板和类模板

6.1 函数模板定义格式:

(1)说明:

template   <typename / class  给某数据类型一个符号>

返回值类型(符号)  函数名 (参数表)

{}

(2)例子:

template  <typename  T , typename  S>

T  max(T  x,  S  y)

{

     cout<<x;

     cout<<y;

     return  x;

}

调用函数时,如max(2,“字符串”),程序就会根据实参来确定模板数据的类型,此处就会将T替换为int,S替换为字符串string。

(3)注意:

1. template为关键字,给某数据类型一个符号可用typename / class但是此处的class和没有关系。

2.函数模板是一个函数“框架”,编译器不会为它产生可执行代码。

6.2 函数模板的使用

和普通函数调用相同,只不过在调用函数给出实参时,才会产生模板函数的可执行代码。

如上例中,调用函数时,如max(2,“字符串”),程序就会根据实参来确定模板数据的类型,此处就会将T替换为int,S替换为字符串string,此时产生模板函数的可执行代码。

7 类模板

类模板又称为参数化的类,即类中的数据类型没有确定,因此类模板并不是真正的类,只有将类模板与某种特点数据类型联系起来,此时才会产生一个实际的类。

类是一组相似对象的公共性质的抽象,类模板是若干功能相似、数据类型又不同的类的公共性质的抽象,类模板是更高层次的抽象。

1.类模板的定义

一般格式:

template  <模板参数表>

class  类模板名

{类体};

说明:

(1)类模板中相关声明和普通类、函数模板类似

(2)在类模板外定义成员函数:

template <模板参数表>

返回值类型  类模板名<模板参数顺序表>::函数名(函数参数表)

{函数体}

2.类模板的使用

定义类模板的一个对象:

类模板名<类模板实参表>  对象名(构造函数实参表)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值