IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 对运算符进行重载【C++】 -> 正文阅读

[C++知识库]对运算符进行重载【C++】

对运算符进行重载【C++】

一、多态性的概念

????????多态性是面向对象程序设计的重要特性之一。

????????多态性主要体现在:向不同的对象发送同一个消息,不同的对象在接收时会产生不同的行

为。也就是说,每个对象可以用自己的方式去响应共同的消息。

????????C++ 支持两种形式的多态性,一种是编译时的多态性,称为静态联编。一种是运行时多态,

称为动态联编。

? ? ? ? 多态的实现:函数重载、运算符重载、虚函数。

二、运算符重载

????????在以前的学习中,C++ 中预定义的运算符的操作对象只能是基本数据类型。实际上,对于很

多用户自定义的类型(如类),也需要有类似的运算操作。

?(1)运算符重载是对已有的运算符赋予多重含义

必要性:C++ 中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类

型(如类)

实现机制:将指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的

实参。编译系统对重载运算符的选择,遵循函数重载的选择原则。

(2)运算符重载规则

????????C++ 中运算符的重载虽然给我们设计程序带来很多的方便,但对运算符的重载时,以下的几

种情况需要注意:

????????a.?一般来说,不改变运算符原有含义,只让它能针对新类型数据的实际需要,对原有运算符

进行适当的改造。例如,重载“+”运算符后,它的功能还是进行加法运算。

????????b.?重载运算符时,不能改变运算符原有的优先级别,也不能改变运算符需要的操作数的数

目。重载之后运算符的优先级和结合性都不会改变。

????????c.?不能创建新的运算符,只能重载 C++?中已有的运算符。

????????d.?有些运算符不能进行重载。如:“ . ” 类成员运算符、“ * ” 类指向运算符、“ :: ”类作用域运符、“ ? : ” 条件运算符及 “ sizeof ”?求字节数运算符。

????????e.?“ = ” “ & ” 不必用户重载

????????运算符重载不能滥用,只有当用户自定义类型上的操作与内置运算符之间存在逻辑对应关系

时,重载的运算符才能使程序显得更自然、更直观。

(3)运算符重载的实现

????????运算符重载的本质就是函数重载。在实现过程中,首先把指定的运算表达式转化为对运算符

函数的调用,运算对象转化为运算符函数的实参,然后根据实参的类型来确定需要调用的函数,这

个过程是在编译过程中完成的。

????????运算符重载形式有两种:重载为类的成员函数和重载为类的友元函数。

a. 运算符重载为类的成员函数

语法形式为:

函数类型 operator 运算符(形参表) {

? ? ? ? 函数体;

}

b. 运算符重载为类的友元函数

运算符重载还可以为友元函数。当重载友元函数时,将没有隐含的参数 this 指针。语法形式如下:

friend 函数类型 operator 运算符(形参表);

重载为类成员函数时:参数个数 = 原操作数个数 - 1(后置 ++、-- 除外);

重载为友元函数时:参数个数 = 原操作数个数,且至少应该有一个自定义类型的形参。

三、双目运算符重载

(1)双目运算符 B

????????如果要重载 B 为类成员函数,使之能够实现表达式 oprd1 B oprd2,其中 oprd1A 类对

象,则 B 应被重载为 A 类的成员函数,形参类型应该是 oprd2 所属的类型。经重载后,表达式

oprd1 B oprd2 相当于 oprd1.operator B(oprd2)。

【题目】将”+”-运算重载为复数类的成员函数。

【规则】实部和虚部分别相加减。

【操作数】两个操作数都是复数类的对象。

#include<iostream>
using namespace std;
class complex {		//复数类声明
	public:	
		//构造函数
		complex(double r = 0.0, double i = 0.0) {
			real = r; 
			imag = i; 
		}
		complex operator + (complex c2);	// + 重载为成员函数
		complex operator - (complex c2);	// - 重载为成员函数
/*
    friend complex operator + (complex c1, complex c2);
        // 运算符 + 重载为友元函数
    friend complex operator - (complex c1, complex c2);
        // 运算符 - 重载为友元函数
*/
		void display();						//输出复数
	private:
		double real;					   //复数实部
		double imag;					   //复数虚部
};
complex complex::operator + (complex c2) {		//重载函数实现
	complex c;
	c.real = c2.real + real;
	c.imag = c2.imag + imag;
	return complex(c.real, c.imag);
}
/*
    // 运算符重载友元函数实现
    complex operator +(complex c1,complex c2) {
    return complex(c2.real+c1.real, c2.imag+c1.imag);
}

*/
complex complex::operator - (complex c2) {		//重载函数实现
	complex c;
	c.real = real - c2.real;
	c.imag = imag - c2.imag;
	return complex(c.real, c.imag);
}
/*
    // 运算符重载友元函数实现
    complex operator -(complex c1,complex c2) {
    return complex(c1.real-c2.real, c1.imag-c2.imag);
}
*/
void complex::display() {
	cout << "(" << real << "," << imag << ")" << endl;
}
int main() {
	complex c1(5, 4), c2(2, 10), c3;  //声明复数类的对象
	cout << "c1 ="; c1.display();
	cout << "c2 ="; c2.display();
	c3 = c1 - c2;					 //使用重载运算符完成复数减法
	cout << "c3 = c1 - c2 =";
	c3.display();
	c3 = c1 + c2;					 //使用重载运算符完成复数加法
	cout << "c3 = c1 + c2 ="; 
	c3.display();
	return 0;
}

?【例】两字符串相加法

#include <iostream>
#include <cstring>
using namespace std;
class String{
    private:
        char name[200];
    public:
        String(char* str) {
            strcpy(name, str); 
        }
        ~String() {}
        String operator+ (const String&);
        void display() {
            cout << "The string is:" << name << endl;
        }
};
static char* str;
String String::operator + (const String& a) {
    strcpy(str, name);
    strcat(str, a.name);
    return String(str);
}
int main() {
    str = new char[200];
    String demo1("Just Do Yourself!1 ");
    String demo2("Just Do Yourself!2 ");
    demo1.display();
    demo2.display();
    String demo3 = demo1 + demo2;
    demo3.display();
    String demo4 = demo3 + "Just Do Yourself!3 ";
    demo4.display();
    delete []str;
    return 0;
}

?(2)双目运算符重载为友元函数

????????如果需要重载一个运算符,使之能够用于操作某类对象的私有成员,可以此将运算符重载为

该类的友元函数。双目运算符 B 重载后,表达式?oprd1 B oprd2?等同于?operator B (oprd1, oprd2

)。例如:将 +-(双目)重载为复数类的友元函数。两个操作数都是复数类的对象。

(3)注意:

? ? ? ? C++ 规定 “ = ”、“ [] ”、“ () ”、" -> "重载为成员函数;“ << ”、“ >> ” 和类型转换运算符重载为

友元函数;一般将双目运算符重载为友元函数,单目运算符和符号运算符重载为成员函数。

四、单目运算符重载

????????类的单目运算符可重载为一个没有参数的非静态成员函数或者带有一个参数的非成员函数,

参数必须是用户自定义类型的对象或者是对该对象的引用。一般情况下,单目运算符最好重载为成

员函数。

????????在 C++ 中,单目运算符有?++?和?--?,它们是变量自动增?1?和自动减?1?的运算符。在类中可以

对这两个单目运算符进行重载。

? ? ? ? “ ++ ” “ -- ” 重载运算符有前缀和后缀两种运算符重载形式,以 “ ++ ” 重载运算符为例,语

法格式为:

函数类型 operator ++?() ;? ? ? ? ???// 前缀运算

使用前缀运算符的格式为:

++ 对象;


函数类型 operator -- ( int );? ? ? ? // 后缀运算

使用后缀运算符的格式为:

对象 ++;

Example:?

// 声明成类成员函数
#include <iostream>
using namespace std;
class Increase {
    public:
        Increase(int x) :value(x) {}
        Increase  operator++();      	//前增量
        Increase operator++(int);     	//后增量
        void display() {
            cout << "The value is " << value << endl;
        }
    private:
        int value;
};
Increase  Increase::operator ++ () {
    value++;                  	//先增量
    return *this;            	//再返回原对象
}
Increase Increase::operator ++ (int) {
    Increase temp(*this);       //临时对象存放原有对象值
    value++;                    //原有对象增量修改
    return temp;                //返回原有对象值
}
int main() {
    Increase n(20);
    n.display();
    (n++).display();            //显示临时对象值
    n.display();                //显示原有对象
    ++n;
    n.display();
    ++(++n);
    n.display();
    (n++)++;              	     //第二次增量操作对临时对象进行
    n.display();
    return 0;
}

//声明成友元函数
#include <iostream>
using namespace std;
class Increase {
    public:
        Increase(int x) :value(x) {}
        friend Increase  operator++(Increase&);     	//前增量
        friend Increase operator++(Increase&, int);    	//后增量
        void display() {
            cout << " The value is " << value << endl; 
        }
    private:
        int value;
};

Increase  operator ++ (Increase& a) {
    a.value++;                       //前增量
    return a;                        //再返回原对象
}
Increase operator ++ (Increase& a, int) {
    Increase temp(a);                //通过拷贝构造函数保存原有对象值
    a.value++;                       //原有对象增量修改
    return temp;                     //返回原有对象值
}
int main() {
    Increase n(20);
    n.display();
    (n++).display();                 //显示临时对象值
    n.display();                     //显示原有对象
    ++n;
    n.display();
    ++(++n);
    n.display();
    (n++)++;                         //第二次增量操作对临时对象进行
    n.display();
    return 0;
}

五、插入和提取运算符重载

????????I / O?流库一个重要的特性——新的数据类型的输入输出。为了实现该功能,用户可以重载“

<<”和“>>”运算符。重载为类的友元函数,一般格式:

friend istream & operator >> (istreaam &,ClassName &);

friend ostream & operator << (ostream &,ClassName &);

?Example:

【例1】重载插入和提取运算符,表示日期。

#include<iostream>
using namespace std;
class Date {
    public:
        Date(int y, int m, int d) {
            Year = y; 
            Month = m;
            Day = d;
        }
        friend ostream & operator << (ostream& os, Date& date);
        friend istream & operator >> (istream& is, Date& date);
    private:
        int Year, Month, Day;
};
ostream& operator << (ostream& os, Date& date) {
    os << date.Year << "/" << date.Month << "/" << date.Day << endl;
    return os;
}
istream& operator >> (istream& is, Date& date) {
    is >> date.Year >> date.Month >> date.Day;
    return is;
}
int main() {
    Date Date1(2021, 7, 1);
    cout << "Current date:" << Date1 << endl;
    cout << "Enter new date:";
    cin >> Date1;
    cout << endl<<"New date:" << Date1 << endl;
    return 0;
}

【例2】复数类问题

#include <iostream>
using namespace std;
class Complex{
    public:
        Complex(double r = 0, double i = 0) {
            Real = r;
            Imag = i;
        }
        Complex& operator + (const Complex& a) {
            Real += a.Real;
            Imag += a.Imag; 
            return *this;
        }
        friend ostream& operator << (ostream& MyStream, const Complex& a);
    private:
        double Real;
        double Imag;
};
ostream& operator << (ostream& MyStream, const Complex& a) {
    MyStream << a.Real << " + " << a.Imag << "i" << endl;
    return MyStream;
}
int main() {
    Complex c1(1, 2), c2(3, 4), z;
    z = c1 + c2;
    cout << c1 << c2 << z;
    return 0;
}

【例3】重载插入和提取运算符,直接输入和输出对象。

#include <iostream>
using namespace std;
class CMoney{
	public:
		friend ostream& operator << (ostream&, CMoney&);
		friend istream& operator >> (istream&, CMoney&);
		CMoney(int m = 0, int c = 0) {
			Dollar = m;
			Cents = c; 
		}
		int Dollar, Cents;		// 公有成员
};
ostream& operator << (ostream& os, CMoney& m) {
	os << m.Dollar << "元" << m.Cents << "分"<<endl;
	return os;
}
istream& operator >> (istream& is, CMoney& m) {
	is >> m.Dollar >> m.Cents;
	return is;
}
int main() {
	CMoney m;
	cout << "输入两个整数:";
	cin >> m;
	cout << m;
	return 0;
}

?六、特殊运算符重载 —— 赋值运算符重载

????????在 C++?中有两种类型的赋值运算符:一类是?“?+=?”??“?-=?”?等先计算后赋值的运算符,另一

类是?“?=?”?即直接赋值的运算符。

1. 运算符 “ += ” “ -= ” 的重载

【例】实现复数类 “ += ” 和 “ -= ” 的重载。

#include <iostream>
using namespace std;
class Complex {
	public:
		Complex(double r, double i) {
			real = r;
			image = i;
		}
		Complex operator -= (Complex& t);
		Complex operator += (Complex& t);
		void Print();
	private:
		double real, image;
};
Complex Complex::operator -= (Complex& t) {
	real -= t.real;	
	image -= t.image;
	return *this;
}
Complex Complex::operator += (Complex& t) {
	real += t.real;
	image += t.image;
	return *this;
}
void Complex::Print() {
	if (image < 0)
		cout << real << image << "i" << endl;
	else 
		cout << real << " + " << image << "i" << endl;
}
int main() {
	Complex c1(5.0, 3.0), c2(2.1, 1.8), c3(5.3, 4.2);
	c1 -= c2; 
	cout << "c1 = ";  
	c1.Print();
	c3 += c2;  
	cout << "c3 = "; 
	c3.Print();
	return 0;
}

?2. 运算符 “ = ” 的重载

【例】实现运算符 “ = ” 的重载。

#include <iostream>
#include <cstring>
using namespace std;
class Message{
	public:
		Message() {
			buffer = NULL;
		}
		~Message() {
			delete buffer;
		}
		void Display() {
			cout << buffer << endl;
		}
		void Set(char* string) {
			if (buffer != NULL) 
				delete buffer;
			buffer = new char[strlen(string) + 1];
			strcpy(buffer, string);
		}
		void operator=(const Message& Message) {
			if (buffer != NULL) 
				delete buffer;
			buffer = new char[strlen(Message.buffer) + 1];
			strcpy(buffer, Message.buffer);
		}
	private:
		char* buffer;
};
int main() {
	Message c1;
	c1.Set("第一条消息");
	c1.Display();
	Message c2;
	c2.Set("第二条消息");
	c2.Display();
	c1 = c2;
	c1.Display();
	return 0;
}

3. 下标运算符重载

????????下标运算符 “[ ]” 通常用于在数组中标识数组元素的位置,下标运算符重载可以实现数组数据

的赋值和取值。下标运算符重载函数只能作为类的成员函数,不能作为类的友元函数。标运算符

“[ ]” 函数重载的一般形式为:

返回类型 类名 :: operator [?] (形参) {

? ? ? ? 函数体

}

// 形参在这里表示下标,规定只能有一个参数

?【例】实现下标运算符 " [ ] " 的重载。

#include <iostream>
using namespace std;
class Demo {
	public:
		Demo (){}
		int& operator[](int i);		// 声明下标运算符 [] 重载函数
	private:
		int Vector[5];
};
int& Demo ::operator[](int i) {		// 定义下标运算符 [] 重载函数
	return	Vector[i];
}
int main() {
	Demo v;
	for (int i = 0; i < 5; i++)
		v[i] = i + 1;
	for (int i = 0; i < 5; i++)
		cout << v[i] << " ";
	cout << endl;
	return 0;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-30 12:34:13  更:2021-07-30 12:34:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/3 9:04:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码