多态性小结
C++第五次作业
一、多态性
多态性是指同样的消息被不同类型的对象接收时导致不同的行为.
1.多态的类型
- 重载多态
- 强制多态
- 包含多态
- 参数多态
- 虚函数是介绍包含多态时的关键内容
2.多态的实现
多态从实现的角度来讲可以划分为两类:编译时的多态和运行时的多态。前者是在编译的过程中确定了同名操作的具体操作对象,而后者则是在程序运行过程中才动态的确定操作所针对的具体对象。
二、运算符重载
定义
运算符的重载是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据时导致不同的行为。
- 运算符重载的实质就是函数的重载。在实现过程中,首先把指定的运算表达式转化为对运算符函数的调用,将运算对象转化为运算符函数的实参。然后根据实参的类型来确定需要调用的函数。
运算符重载的规则
1.C++中运算符除了少数几个之外,全部可以重载,而且只能重载C++中有的运算符。
2.重载之后运算符的优先级和结合性都不会改变。
3.运算符重载是针对新类型数据的实际需要,不能改变原运算符的操作对象个数。同时至少要有一个操作对象是自定义类型。
运算符重载为类的成员函数的一般语法形式:
返回类型 operator 运算符(形参表):
{
函数体
}
运算符重载为非成员函数的一般语法形式:
返回类型 operator 运算符(形参表):
{
函数体
}
- 当以非成员函数形式重载运算符时,有时需要访问运算符参数所涉及类的私有成员,这时可以把该函数声明为类的友元函数。
- 当函数重载为类的成员函数时,函数的参数个数比原来的操作数要少一个(后置++,--除外)
- 当函数重载为非成员函数时,函数参数与操作个数相同
具体实例——运算符重载为成员函数
举例1如下:
运行结果如下:
- 除了在函数声明及实现的时候用到了关键字operator,运算符重载函数成员与类的普通成员函数没有什么区别.
举例2如下:
将单目运算符++重载为成员函数形式:
运行结果如下:
- 前置单目运算符和后置单目运算符的重载最主要区别就在于重载函数的形参。
- 前置单目运算符重载为函数的时候没有形参,而后置单目运算符重载为成员函数的时候需要有一个int型形参。
具体实例——运算符重载为非成员函数
运算符所需要的操作数都需要通过函数的形参表来传递,在形参表从左到右的顺序就是运算符操作数的顺序。
如果需要访问运算符参数对象的私有成员,可以将该函数声明为类的友元函数。
运行结果如下:
- 这个例子中重载了“<<"运算符,可以对cout使用“<<"操作符来输出一个Complex对象,使输出变得更加方便直观。
三、虚函数
虚函数是动态绑定的基础。虚函数必须是非静态的成员函数。
虚函数经过派生之后,在类族中就可以实现运行过程中的多态。
如果需要通过基类的指针指向派生类的对象,并访问某个与基类同名的成员,那么首先在基类中将这个同名函数说明为虚函数。这样通过基类类型的指针就可以使属于不同派生类的不同对象产生不同的行为,从而实现运行的多态。
一般虚函数成员
声明语法:
virtual 函数类型 函数名(形参表);
- 实际上就是在类的定义中使用virtual关键字来限定成员函数,函数声明只能出现在类定义中的函数原型盛宁中,而不能再成员函数实现的时候。
运行中的多态需要满足的条件
1.类之间满足赋值兼容规则。
2.要声明虚函数。
3.要由成员函数来调用或者是通过指针,引用来访问虚函数。
- 虚函数一般不声明为内联函数,因为对虚函数的调用需要动态绑定,而对内联函数的处理是静态的,所以虚函数一般不能以内联函数处理。
虚函数成员举例如下:
运行结果如下:
现在我们来对指针指向来做一个小测验。
运行结果就会发生改变:
- 用指向派生类对象的指针仍然可以调用基类中被派生类覆盖的成员函数,方法是使用::进行限定。
虚析构函数
在C++中不能声明虚构造函数,但是可以声明虚析构函数。
语法形式:
virtual ~类名();
纯虚函数与抽象类
抽象类是一种特殊的类,它为一个类族提供统一的操作界面。
纯虚函数
纯虚函数是一个在基类中声明的虚函数,它在该基类中没有定义具体的操作内容,要求各派生类根据实际需要给出各自的定义。
语法形式:
virtual 杉树类型 函数名(参数表)=0;
- 它与一般虚函数成员的原型在书写格式上的不同就在于后面加了“=0”,声明为纯虚函数之后,基类中就可以不再给出函数的实现部分。纯虚函数的函数体由派生类给出。
- 基类中仍然允许对纯虚函数给出实现,但即使给出实现,也必须由派生类覆盖,否则无法实例化。
- 在基类中对纯虚函数定义的函数体的调用,必须通过“基类名::函数名(参数表)”的形式。
抽象类
带有春虚函数的类是抽象类。抽象类的主要作用是通过它为一个类族建立一个公共的接口,使它们能够更有效的发挥多态特性。
抽象类声明了一个类族派生类的共同接口,而接口的完整实现,即纯虚函数的函数体,要由派生类自己定义。
- 抽象类不能实例化,即不能定义一个抽象类的对象。但可以定义一个抽象类的指针和引用。
通过指针或引用,就可以指向并访问派生类的对象,进而访问派生类的成员。
举例如下:
运行结果如下: