一、C++的重载多态
面向对象的多态性可以分为重载多态、强制多态、包含多态和参数多态四类,重载多态和强制多态统称为专用多态,包含多态和参数多态统称为通用多态。
C++允许功能相近的函数在相同的作用域内以相同函数名定义,从而形成重载,普通函数及类的成员函数的重载、运算符重载均属于重载多态。重载多态使得程序员方便使用且易于记忆特殊方法及符号,本文将基于重载多态进行展开学习。
二、普通函数的重载
普通函数的重载。两个以上的函数,具有相同的函数名,但是形参的个数或者类型不同,编译器根据实参和形参的类型及个数的最佳匹配,自动确定调用哪一个函数。
普通函数的重载规则:
1. 重载函数必须具有相同的函数名。不要将不同功能的函数定义为重载函数,以免出现对调用结果的误解、混淆;
2. 重载函数参数列表必须不同(参数个数不同、参数类型不同、不同参数类型的排列顺序不同);
3. 重载函数返回值类型可以相同,也可以不相同。
注意事项:
1. 编译程序对实参和形参的类型及个数进行最佳匹配,从而来选择对应调用函数。如果函数名相同,形参类型也相同(无论函数返回值类型是否相同),在编译时会被认为是语法错误;
2. 当使用具有默认形参值的函数重载形式时,需要注意防止二义性。C++函数默认形参值必须在形参列表的末尾,在重载函数的未知值形参类型及个数与函数原型一致且重载函数没有默认形参值,同时函数原型有默认形参值的情况下,仅提供未知值形参的实参以调用函数在编译时便无法区分为不同的重载形式。
三、类的成员函数的重载
类的成员函数的重载。类的成员函数的重载一般与普通函数的重载几乎相同,但类的成员函数的重载包含常成员函数(const关键字可以用于对重载函数的区分)这一特殊情况。使用const关键字修饰的函数为常成员函数,常成员函数声明的格式如下:
函数返回值类型 函数名(参数表) const;
注意事项[1]:
1. const是函数类型的一个组成部分,因此在函数的定义部分也要带const关键字;
2. 如果将一个对象说明为常对象,则通过该常对象只能调用它的常成员函数,而不能调用其他成员函数;
3. 无论是否通过常对象调用常成员函数,在常成员函数调用期间,目的对象都被视同为常对象,因此常成员函数不能更新目的对象的数据成员,也不能针对目的对象调用该类中没有用const修饰的成员函数;
4. 如果仅以const关键字为区分对成员函数重载,那么通过非const的对象调用该函数,两个重载的函数都可以与之匹配,这时编译器将选择最近的重载函数——不带const关键字的函数。
四、运算符重载
运算符重载。运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据时导致的不同行为。运算符重载的本质就是函数重载。
运算符的重载形式有两种,即重载为类的非静态成员函数和重载为非成员函数。运算符重载为类的成员函数的一般语法形式为:
函数返回值类型 operator运算符(形参表) {函数体};
运算符重载形式[1]:
1. 运算符重载为成员函数,它就可以自由地访问本类的数据成员。如果是双目运算符,左操作数是对象本身的数据,由this指针给出,右操作数则需要通过运算符重载函数的参数表来传递;如果是单目运算符,操作数由对象的this指针给出,就不再需要任何参数。
2. 运算符重载为非成员函数,运算所需要的操作数都需要通过函数的形参表来传递,在形参表中形参从左到右的顺序就是运算符操作数的顺序。如果需要访问运算符参数对象的私有成员,可以将该函数声明为类的友元函数。
运算符重载规则[1]:
1. C++中的运算符除了少数几个之外(如类属关系运算符"."、成员指针运算符".*"、作用域分辨符"::"和三目运算符”?:“),全部可以重载,而且只能重载C++中已经有的运算符;
2. 重载之后运算符的优先级和结合性都不会改变;
3. 运算符重载是针对新类型数据的实际需要,对原有运算符进行适当的改造。一般来讲,重载的功能应当与原有功能相类似,不能改变原运算符的操作对象个数,同时至少要有一个操作对象是自定义类型。
五、代码实验
/*
* 复数数据类型的操作符重载
*/
#include <iostream>
using namespace std;
class complex
{
public:
complex() {};
complex(double r, double i) :real(r), image(i) {};
complex(const complex& c) { real = c.real; image = c.image; };
~complex() {};
complex operator+(const complex& c) const;
complex operator-(const complex& c) const;
void display() const;
private:
double real;
double image;
};
complex complex::operator+(const complex& c)const
{
return complex(real + c.real, image + c.image);
};
complex complex::operator-(const complex& c)const
{
return complex(real - c.real, image - c.image);
};
void complex::display() const
{
cout << "(" << real << "," << image << ")" << endl;
};
int main()
{
complex c1(1,1), c2(2,2),c3,c4;
c3 = c1 + c2;
c4 = c2.operator-(c1);
c3.display();
c4.display();
return 0;
};
参考资料:
[1] C++语言程序设计 / 郑莉,董渊,何江舟编著.—4版.—北京:清华大学出版社,2010.7(清华大学计算机系列教材)
[2] C++ Primer中文版:第5版 /(美)李普曼(Lippman,S.B.),(美)拉乔伊(Lajoie,J.),(美)默(Moo,B.E.)著;王刚,杨巨峰译. —北京:电子工业出版社,2013.9.