您的位置:首页 > 编程语言 > C语言/C++

C++(6)/运算符重载(一)

2017-05-12 17:56 155 查看
运算符重载的概念

什么是运算符重载?

重载的意思就是添加。使用同一个函数名提供多个接口就是函数重载。运算符重载本质上就是函数重载,其函数名为operator 操作符。调用操作符时,可以使用标准的函数调用,也可以直接当做运算符来使用。

实际上, 计算机对整数、单精度数和双精度数的加法操作过程是很不相同的,但由于C++已经对运算符”+”进行了重载,所以就能适用于int,float,double类型的运算。

又如”<<“是C++的位运算中的位移运算符(左移),但在输出操作中又是与流对象cout配合使用的流插入运算符,”>>“也是位移运算符(右移),但在输入操作中又是与流对象cin配合使用的流提取运算符。这就是运算符重载(operator overloading)。C++系统对”<<“和”>>“进行了重载,用户在不同的场合下使用它们时,作用是不同的。

运算符重载的规则

什么操作符不能重载?

. 点操作符

.* 点星操作符

:: 作用域操作符

三目运算符

操作符重载的一般规则

只能对已有的 C++运算符进行重载

只有4个运算符不能被重载

重载不能改变运算符运算对象(即操作数)的个数

重载不能改变运算符的优先级别

重载不能改变运算符的结合性

重载运算符的函数不能有默认的参数

重载运算符的参数至少应有一个是类对象(或类对象的引用)

<
4000
li>用于类对象的运算符一般必须重载,但有两个例外,运算符”=“和运算符”&“不 必用户重载

应当使重载运算符的功能类似于该运算符作用于标准类型数据时候时所实现的功能

运算符重载函数可以是类的成员函数,也可以是类的友元函数,还可以是既非类的成员函数也不是友元函数的普通函数

运算符重载方法

运算符重载有两个方法:一个是利用全局函数进行运算符重载;另一种是利用成员函数进行运算符重载。

利用全局函数

对双目运算符来说第一个参数为左操作数,第二个参数为右操作数

对单目运算符来说,参数为操作数

利用成员函数

对双目运算符来说左操作数为当前对象,右操作数为函数参数

对单目运算符来说,操作数为当前对象

为什么要进行运算符重载?

我们知道,数据类型开辟了内存用于存放变量和提供了基于变量值的运算。类定义了对象,提供了一种新的数据存储方法。所以要提供相应的对数据对象的操作,这就是运算符重载。

运算符重载的练习

重载复数的加减法

重载双目运算符: 复数
+=
-=
操作符

重载单目运算符: 前
++
和 前
--


重载单目运算符: 后
++
和 后
--


重载输入输出操作符

重载赋值操作符

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>

using namespace std;

/*定义复数类Complex 实现
1.基本运算符+ - 重载
2.双目运算符 += -=重载
3.单目运算符 前++ 前-- 后++ 后--的重载
4.输入输出运算符重载
*/

class Complex{
/*友元函数*/
friend void operator<<(ostream & os, Complex &c);
friend void operator>>(istream & is, Complex &c);
private:
/*私有属性:复数的实部和虚部*/
double m_real;
double m_virtual;
public:
/*无参数的构造函数*/
Complex(){
this->m_real = 0;
this->m_virtual = 0;
}

/*带参数的构造函数*/
Complex(double m_real, double m_virtual){
this->m_real = m_real;
this->m_virtual = m_virtual;
}

/*运算符重载: + - */
Complex operator +(Complex &c1){
return Complex(this->m_real + c1.m_real, this->m_virtual + c1.m_virtual);
}
Complex operator -(Complex &c1){
return Complex(this->m_real - c1.m_real, this->m_virtual - c1.m_virtual);
}
/*运算符重载: += 和 -= */
/*实现 x1+=x2+=x3 这样的连加功能 */
Complex & operator += (Complex &c1){
this->m_real += c1.m_real;
this->m_virtual += c1.m_virtual;
return *this;
}
Complex& operator -=(Complex & c1){
this->m_real -= c1.m_real;
this->m_virtual -= c1.m_virtual;
return *this;
}
/*运算符重载: 前++和前--*/
Complex & operator++ (){
this->m_real++;
this->m_virtual++;
return *this;
}
Complex & operator-- (){
this->m_real--;
this->m_virtual--;
return *this;
}
/*运算符重载: 后++和后--*/
const Complex operator++ (int){
Complex temp = *this;
this->m_real++;
this->m_virtual++;
return temp;
}
const Complex operator-- (int){
Complex temp = *this;
this->m_real--;
this->m_virtual--;
return temp;
}
};

/*全局函数部分*/

/*重载输出运算符*/
/*输入输出运算符重载为了保持形式和标准输入输出一致,只能使用全局函数来重载左移运算符*/
void operator<<(ostream & os, Complex &c){
if (c.m_virtual > 0){
os << "complex number is " << c.m_real << "+i" << c.m_virtual << endl;
}
else if (c.m_virtual == 0){
os << "complex number is " << c.m_real << endl;
}
else{
os << "complex number is " << c.m_real << "-i" << abs(c.m_virtual) << endl;
}
}

/*重载输入运算符*/
/*输入输出运算符重载为了保持形式和标准输入输出一致,只能使用全局函数来重载左移运算符*/
void operator>>(istream & is, Complex & c){
cout << "please input the real part of the complex:";
is >> c.m_real;
cout << "please input the virtual part of the complex:";
is >> c.m_virtual;
}

/*定义Student类实现
5.赋值运算符重载
*/
class Student{
/*private属性中有在堆内存中存储的属性,所以必须要实现深拷贝才能保证在对象构造和析构的时候不出错*/
/*C++编译器默认为我们提供拷贝构造函数和默认重载的赋值运算符,我们要手动重载这两个函数*/
friend void operator<<(ostream & os, Student &s);
private:
int id;
char *name;
public:
Student(int id, char *name){
this->id = id;

int len = strlen(name) + 1;
this->name = new char[len];
strcpy(this->name, name);
}

Student(const Student& s){
this->id = id;
int len = strlen(s.name) + 1;
this->name = new char[len];
strcpy(this->name, name);
}

~Student(){
if (this->name != NULL){
delete[] this->name;
this->name = NULL;
}
this->id = -1;
}

Student& operator = (const Student& s){
/*重载赋值运算符和重载拷贝构造函数有所不同!!!*/
/*因为拷贝构造函数是在实例化一个对象的时候给对象赋值,对象中的属性此时并没有值,不用考虑先释放对象已有的内存空间*/
/*而赋值运算符是给一个已经存在的对象赋值,需要考虑是否释放原有的内存空间*/
if (this->name != NULL){
delete[] this->name;
this->name = NULL;
}//先释放原有的堆内存空间
this->id = s.id;
int len = strlen(s.name) + 1;
this->name = new char[len];
strcpy(this->name, s.name);

return *this;
}

};

void operator<<(ostream & os, Student &s){
os << "student's id is: " << s.id << "student's name is: " << s.name << endl;
}

/*测试模块部分*/

void test01()/*测试复数的加法和减法功能,以及重载输出的运算符*/{
Complex c1(1, 1), c2(2, 3);
Complex c3 = c1 + c2;
Complex c4 = c1 - c2;
cout << c3;
cout << c4;
}
void test02()/*实现 连+= 和 连-= 功能*/{
Complex c1(1, 1), c2(2, 3),c3(3,4);
c1 += c2 += c3;
cout << "c1 is :";
cout << c1;
cout << "c2 is: ";
cout << c2;

c1 -= c2-=c3;
cout << "c1 is :";
cout << c1;
cout << "c2 is: ";
cout << c2;
}

void test03()/*实现 前连++ 和 前连-- 功能*/{
Complex c1(1, 1);
++++c1;
cout << c1;
----c1;
cout << c1;

}

void test04()/*实现 后++ 和 后-- 功能*/{
Complex c1(1, 1);
Complex temp1=c1++;
cout << temp1;
cout << c1;
c1--;
cout << c1;
}

void test05()/*重载输入输出运算符*/{
Complex c1;
cin >> c1;
cout << c1;
}

void test06(){
Student s1(1, "anran"), s2(2, "yinjuan"), s3(3, "baobao");
cout << s1;
cout << s2;
cout << s3;
s1 = s2 = s3; //=操作符的执行优先级是从右往左
cout << s1;
cout << s2;
cout << s3;
}

int main(void){

//test01();
//test02();
//test03();
//test04();
//test05();
test06();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: