目录
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.类模板的使用
定义类模板的一个对象:
类模板名<类模板实参表> 对象名(构造函数实参表)。