失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > C++ 重载运算符和重载函数

C++ 重载运算符和重载函数

时间:2021-10-30 13:54:38

相关推荐

C++ 重载运算符和重载函数

参考:/cplusplus/cpp-overloading.html

/CaiNiaoZJ/archive//08/12/2136598.html

前言:

运算符重载和函数重载体现了面向对象技术的多态性。多态性机制不仅增加了面向对象软件系统的灵活性,进一步减少了冗余信息,而且显著提高了软件的可重用性和可扩充性。

从实现的角度来讲,多态性可以划分为两类:编译时的多态性和运行时的多态性。在C++语言中,编译时的多态性主要是通过函数重载和运算符重载实现的。

本文主要讲的是编译时多态,因为编译时多态主要是通过函数重载和运算符重载实现的。

运行时多态之后再讲。

C++允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载。

一、C++ 中的函数重载

概念

重载:是指运行存在多个同名函数,而这些函数的参数列表不同(参数个数、类型、顺序),不能使用返回值作为区分。

关键词:同一作用域内,具有相同函数名,不同参数列表

原理

重命名机制(name mangling):

编译器根据函数不同的参数表,对同名函数的名称进行函数修饰,从而这些同名函数就成为了不同的函数(至少对于编译器来说是这样的)。该过程在编译器间就已经确定了,也就是说在编译期就绑定了(早绑定)。

区分

C语言是不支持函数重载的,这里涉及另外一个知识点:C++在兼容C时的extern "C"的用法。

代码实例

#include<iostream>using namespace std;void print(int i){cout<<"print a integer :"<<i<<endl;}void print(string str){cout<<"print a string :"<<str<<endl;}int main(){print(12);print("hello world!");return 0;}

二、C++ 中的运算符重载

2.0 使用全局函数进行运算符重载(数据成员为public属性)

C++就为运算符重载提供了一种方法,即运算符重载函数。其函数名字规定为operator后紧跟重载运算符。比如:operator+(),operator*()等。现在我们给出一个加法运算符的重载函数用于完成复数的加法运算:

#include <iostream>using namespace std;class Complex //复数类{public:double real;//实数double imag;//虚数Complex(double real=0,double imag=0){this->real=real;this->imag=imag;}};Complex operator+(Complex com1,Complex com2)//运算符重载函数{return Complex(com1.real+com2.real,com1.imag+com2.imag);}int main(){Complex com1(10,10),com2(20,20),sum;sum=com1+com2;//或sum=operator+(com1,com2)cout<<"sum的实数部分为: "<<sum.real<<endl;cout<<"sum的虚数部分为: "<<sum.imag<<"i"<<endl;return 0;}

输出:

sum的实数部分为: 30sum的虚数部分为: 30i

上述示例中的运算符重载函数是不属于任何的类,是全局的函数。因为在Complex类(复数类)中的数据成员是公有的性质,所以运算符重载函数可以访问。但如果定义为私有的呢,那该怎么办。其实,在实际的运算符重载函数声明当中,有两种方法:

定义其为要操作类的成员函数或类的友元函数

2.1 运算符重载函数作为类的友元函数的形式:

友元函数重载双目运算符(有两个操作数,通常在运算符的左右两则),参数表中的个数为两个。若是重载单目运算符(只有一个操作数),则参数表中只有一参数。

class 类名{friend 返回类型 operator运算符(形参表);}类外定义格式:返回类型 operator运算符(参数表){函数体}

1) 友元函数重载双目运算符(+)

#include <iostream>using namespace std;class Complex //复数类{//私有数据 private:double real;//实数double imag;//虚数public: Complex(double real=0,double imag=0){this->real=real;this->imag=imag;}//友元函数重载双目运算符friend Complex operator+(Complex com1,Complex com2);void showSum();};Complex operator+(Complex com1,Complex com2)//运算符重载函数{return Complex(com1.real+com2.real,com1.imag+com2.imag);}void Complex::showSum(){if(imag>=0){cout<<real<<"+"<<imag<<"i"<<endl;}else{cout<<real<<imag<<"i"<<endl;}}int main(){Complex com1(10,10),com2(20,20),sum;sum=operator+(com1,com2);//或 sum=com1+com2sum.showSum();return 0;}

2) 友元函数重载单目运算符(++):

#include <iostream>using namespace std;class Point//坐标类{private:int x;int y;public:Point(int x,int y){this->x=x;this->y=y;}friend void operator++(Point& point);//友元函数重载单目运算符++void showPoint();};void operator++(Point& point)//友元运算符重载函数{++point.x;++point.y;}void Point::showPoint(){std::cout<<"("<<x<<","<<y<<")"<<std::endl;}int main(){Point point(10,10);++point;//或operator++(point)point.showPoint();//输出坐标值return 0;}

输出

(11,11)

2.2 运算符重载函数作为类的成员函数的形式:

对于成员函数重载运算符而言,双目运算符的参数表中仅有一个参数,而单目则无参数。同样的是重载,为什么和友元函数在参数的个数上会有所区别的。原因在于友元函数,没有this指针。

class 类名{返回类型 operator 运算符(形参表);}类外定义格式:返回类型 类名:: operator 运算符(形参表){函数体;}

1) 成员函数重载双目运算符(+):

#include <iostream>using namespace std;class Complex //复数类{//私有数据 private:double real;//实数double imag;//虚数public: Complex(double real=0,double imag=0){this->real=real;this->imag=imag;}//成员函数重载双目运算符Complex operator+(Complex com1);void showSum();};Complex Complex::operator+(Complex com1){return Complex(real+com1.real,imag+com1.imag);}void Complex::showSum(){if(imag>=0){cout<<real<<"+"<<imag<<"i"<<endl;}else{cout<<real<<imag<<"i"<<endl;}}int main(){Complex com1(10,10),com2(200,200),sum;sum=com1+com2;//或 sum=com1.operator+(com2);sum.showSum();return 0;}

2)成员函数重载单目运算符(++)

#include <iostream>using namespace std;class Point//坐标类{private:int x;int y;public:Point(int x,int y){this->x=x;this->y=y;}void operator++();//成员函数重载单目运算符++void showPoint();};void Point::operator++()//成员运算符重载函数{++x;++y;}void Point::showPoint(){std::cout<<"["<<x<<","<<y<<"]"<<std::endl;}int main(){Point point(10,10);++point;//或operator++(point)point.showPoint();//输出坐标值return 0;}

输出

[11,11]

三、重载输出运算符<<

#include<iostream>using namespace std;class People{public:People(int id,int pwd):m_id(id),m_pwd(pwd){}~People(){}friend ostream& operator<< (ostream &os,People p);private:int m_id;int m_pwd;};ostream& operator << (ostream &os, const People p){os<<"your id is:"<<p.m_id<<" and password is:"<<p.m_pwd<<endl;return os;}int main() {People a(1,123);People b(2,456);cout << a<<b;}输出:your id is:1 and password is:123your id is:2 and password is:456

注:

输出运算符的第一个形参是非常量ostream对象的引用。之所以非常量是因为向流写入内容会改变其状态;而该形参是引用是因为我们无法直接复制一个ostream对象。

第二个形参一般是常量引用,该常量是我们要打印的类类型,之所以是常量是因为我们打印一般不会改变对象内容;是引用是我们希望避免复制形参。

返回值返回的是ostream类对象的引用,为了与其他输出运算符保持一致,operator<<一般要返回它的ostream形参。同时为了进行连续的运算,如cout<<a<<b; 先打印类对象a,返回对象引用后继续打印b。

如果觉得《C++ 重载运算符和重载函数》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。