cpp►常见运算符的重载

Posted itzyjr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cpp►常见运算符的重载相关的知识,希望对你有一定的参考价值。

流插入运算符<<:insertion operator (<<)

#include <iostream>
int main() {
	std::cout << "Hello world!";// print Hello world! to console
	return 0;
}

在这个程序中,我们包含了< iostream>以便能够访问std::cout。在主函数内部,我们使用std::cout以及插入操作符(<<)发送文本Hello world! 到要打印的控制台

最初,<<运算符是C和C++的位运算符,将值中的位左移。ostream类对该运算符进行了重载,将其转换为一个输出工具。前面讲过,cout是一个ostream对象,它是智能的,能够识别所有的C++基本类型。这是因为对于每种基本类型,ostream类声明中都包含了相应的重载的operator<<( )定义。也就是说,一个定义使用int参数,一个定义使用double参数,等等。

流提取运算符>>:extraction operator (>>)

#include <iostream>  // for std::cout and std::cin
int main() {
    std::cout << "Enter a number: "; // ask user for a number
    int x{ }; // define variable x to hold user input (and zero-initialize it)
    std::cin >> x; // get number from keyboard and store it in variable x
    std::cout << "You entered " << x << '\\n';
    return 0;
}
Enter a number: |4<Enter>
You entered 4

cin(代表“字符输入”)使用提取操作符(>>)从键盘读取输入。输入必须存储在要使用的变量中

重载<<、>>运算符

要重载运算符,需使用被称为运算符函数的特殊函数形式。运算符函数的格式如下:operatorop(argument-list)
将两个Saleperson对象的销售额相加,则如果district2、sid和sara都是Salesperson类对象,便可以编写这样的等式:district2 = sid + sara;
编译器发现,操作数是Salesperson类对象,因此使用相应的运算符函数替换上述运算符:district2 = sid.operator+(sara);

cout 是 ostream 类的对象。ostream 类和 cout 都是在头文件< iostream>中声明的。ostream 类将<<重载为成员函数,而且重载了多次。
➀为了使cout<<"Star War"能够成立,ostream 类需要将<<进行如下重载:

ostream& ostream::operator << (const char* s) {
    //输出s的代码
    return * this;
}

➁为了使cout<<5;能够成立,ostream 类还需要将<<进行如下重载:

ostream& ostream::operator << (int n) {
    //输出n的代码
    return *this;
}

重载函数的返回值类型为ostream的引用,并且函数返回 *this,就使得cout<<“Star War”<<5能够成立。

cout<<"Star War"<<5;
等价于:
(cout.operator<<("Star War")).operator<<(5);

调用cout << person应使用cout对象本身,而不是它的拷贝,因此该函数按引用(而不是按值)来传递该对象。这样,表达式cout << person将导致os成为cout的一个别名;而表达式cerr << person将导致os成为cerr的一个别名。

cin 是 istream 类的对象,是在头文件< iostream>中声明的。istream 类将>>重载为成员函数。

下面是重载<<与>>的完整例子:

#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
class Complex {
private:
    double real,imag;   
public:
    Complex(double r=0, double i=0): real(r), imag(i){ };
    friend ostream & operator<<(ostream& os, const Complex& c);
    friend istream & operator>>(istream& is, Complex& c);
};
ostream & operator<<(ostream& os, const Complex& c) {
    os << c.real << "+" << c.imag << "i"; //以"a+bi"的形式输出
    return os;
}
istream & operator>>(istream& is, Complex& c) {
    string s;
    is >> s;// 将"a+bi"作为字符串读入, "a+bi" 中间不能有空格
    int pos = s.find("+", 0);
    string sTmp = s.substr(0, pos);// 分离出代表实部的字符串
    c.real = atof(sTmp.c_str());// atof库函数能将const char*指针指向的内容转换成 float
    sTmp = s.substr(pos + 1, s.length() - pos - 2);// 分离出代表虚部的字符串
    c.imag = atof(sTmp.c_str());
    return is;
}
int main() {
    Complex c;
    int n;
    cin >> c >> n;
    cout << c << "," << n;
    return 0;
}
|13.2+133i 87<Enter>
13.2+133i,87
cout << complex;
将被转换为下面的调用:
operator<<(cout, complex);
而该调用返回cout对象。因此,下面的语句可以正常工作:
cout << "Complex:" << complex<< " (Done)\\n";

这个operator<<()版本还可用于将输出写入到文件中:

#include<fstream>
...
ofstream fout;
fout.open("savetime.txt");
Time trip(12, 40);// 12hours,40minutes
fout << trip;
最后一条语句转换为:
operator<<(fout, trip);
类继承让ostream引用能够指向ostream对象和ofstream对象。
重载二元运算符 +、-、*
// mytime.h
#include <iostream>
class Time {
private:
	int hours;
	int minutes;
public:
	Time();
	Time(int h, int m = 0);
	Time operator+(const Time& t) const;
	Time operator-(const Time& t) const;
	Time operator*(double n) const;
};
// mytime.cpp
#include "mytime.h"
Time::Time() {
	hours = minutes = 0;
}
Time::Time(int h, int m) {
	hours = h;
	minutes = m;
}
Time Time::operator+(const Time& t) const {
	Time sum;
	sum.minutes = minutes + t.minutes;
	sum.hours = hours + t.hours + sum.minutes/60;
	sum.minutes %= 60;
	return sum;
}
Time Time::operator-(const Time& t) const {
	Time diff;
	int tot1, tot2;
	tot1 = t.minutes + 60 * t.hours;
	tot2 = minutes + 60 * hours;
	diff.minutes = (tot2 - tot1) % 60;
	diff.hours = (tot2 - tot1) / 60;
	return diff;
}
Time Time::operator*(double mult) const {
	Time result;
	long totalminutes = hours * mult * 60 + minutes * mult;
	result.hours = totalminutes / 60;
	result.minutes = totalminutes % 60;
	return result;
}
// usetime.cpp
#include "mytime.h"
int main() {
	Time t1(3, 35);
	Time t2(2, 48);
	Time temp1 = t1 + t2;// 运用重载运算符operator+
	Time temp2 = t1 * 1.17;// 运用重载运算符operator*
	// display...
}

如果将mytime.h中的重载运算符成员函数,多加一个参数,则会报错

重载一元运算符 负号-、逻辑非!、递增++、递减–

一元运算符只对一个操作数进行操作。

class Distance {
private:
	int feet;// 0到无穷
	int inches;// 0到12
public:
	Distance(int f, int i) {
		feet = f;
		inches = 0;
	}
	Distance operator-() {// 重载负号-一元运算符
		feet = -feet;
		inches = -inches;
		return Distance(feet, inches);
	}
};
int main() {
	Distance D1(11, 10), D2(-5, 11);
	-D1;// 取相反数
	-D2;
	// display...
}
class Complex {
private:
	double i;
	double j;
public:
	Complex(int = 0, int = 0);
	Complex operator++();// 前缀自增
	Complex operator++(int);// 后缀自增,参数需要加上int
};

Complex::Complex(int a, int b) {
	i = a;
	j = b;
}
Complex Complex::operator++() {
	++i;
	++j;
	return *this;
}
Complex Complex::operator++(int) {
	Complex temp = *this;
	++*this;
	return temp;
}

int main() {
	Complex com1(2, 2), com2, com3;
	com2 = ++com1;
	com3 = com1++;
	// display...
}
重载关系运算符 <、>、<=、>=、==
class Distance {
private:
	int feet;
	int inches;
public:
	Distance(int f, int i) {
		feet = f;
		inches = i;
	}
	bool operator<(const Distance& d) {
		if (feet < d.feet || (feet == d.feet && inches < d.inches))
			return true;
		return false;
	}
};

int main() {
	Distance D1(11, 10), D2(5, 11);
	if (D1 < D2) {
		// display...
	}
	return 0;
}
重载输入/输出运算符 <<、>>
class Distance {
private:
	int feet;
	int inches;
public:
	Distance(int f=0, int i=0) {
		feet = f;
		inches = i;
	}
	friend ostream& operator<<(ostream& output, const Distance& D) {
		output << "F=" << D.feet << ",I=" << D.inches;
		return output;
	}
	friend istream& operator>>(istream& input, const Distance& D) {
		input >> D.feet >> D.inches;
		return input;
	}
};

int main() {
	Distance D1(11, 10), D2(5, 11), D3;
	cout << "Enter the value of object:" << endl;
	cin >> D3;
	cout << "First Distance:" << D1 << endl;
	cout << "Second Distance:" << D2 << endl;
	cout << "Third Distance:" << D3 << endl;
	return 0;
}
Enter the value of object:
|70<Enter>
|10<Enter>
First Distance:F=11,I=10
Second Distance:F=5,I=11
Third Distance:F=70,I=10

cout << D1; 将被转换为的调用:operator<<(cout, D1); 由于是非成员函数,所以不可能是调用D1.operator<<(cout)!

重载赋值运算符 =
class Distance {
private:
	int feet;
	int inches;
public:
	Distance(int f, int i) {
		feet = f;
		inches = i;
	}
	void operator=(const Distance& D) {
		feet = D.feet;
		inches = D.inches;
	}
};

int main() {
	Distance D1(11, 10), D2(5, 11);
	D1 = D2;// 使用赋值运算符
	// display D1:F=5,I=11
	return 0;
}
重载函数调用运算符 ()
class Distance {
private:
	int feet;
	int inches;
public:
	Distance(int f=0, int i=0) {
		feet = f;
		inches = i;
	}
	Distance operator()(int a, int b, int c) {
		Distance D;
		// 进行随机计算
		D.feet = a + c + 10;
		D.inches = b + c + 100;
		return D;
	}
};

int main() {
	Distance D1(11, 10), D2;
	D2 = D1(10, 10, 10);// or D2(10,10,10), 调用operator()
	// display D2:F=30,I=120
	return 0;
}
重载下标运算符 []
const int SIZE = 10;
class Safearay {
private:
	int arr[SIZE];
public:
	Safearay() {
		register int i;
		for (i = 0; i < SIZE; i++)
			arr[i] = i;
	}
	int& operator[](int i) {
		if (i > SIZE)
			cout << "索引超过最大值" << endl;
			return arr[0];// 返回第一个元素
		}
		return arr[i];// 因arr数组是全局变量,不会在{}局部作用域销毁,所以返回引用
	}
};

int main() {
	Safearay A;
	cout << "A[5]的值为:" << A[5] << endl;
	cout << "A[12]的值为:" << A[12] << endl;
	return 0;
}
A[5]的值为:5
索引超过最大值
0
重载类成员访问运算符 ->

运算符->必须是一个成员函数。如果使用->运算符,返回类型必须是指针或者是类的对象。
间接引用运算符->可被定义为一个一元后缀运算符。

class Ptr {
	// ...
	ClzX* operator->();
};

类Ptr的对象可用于访问类ClzX的成员。使用方式与指针用法十分相似:

void f(Ptr p) {
	p->m = 10;
}

语句p->m被解释为(p.operator->())->m。上述代码意思即是类ClzX的成员m被赋值为10。

智能指针:
运算符 -> 通常与指针引用运算符 * 结合使用,用于实现"智能指针"的功能。这些指针是行为与正常指针相似的对象,唯一不同的是,当您通过指针访问对象时,它们会执行其他的任务。比如,当指针销毁时,或者当指针指向另一个对象时,会自动删除对象。

// 假设一个实际的类
class Obj {
private:
	static int i, j;
public:
	void f() const { cout << i++ << endl; }
	void g() const { cout << j++ << endl; }
};

// 静态成员定义
int Obj::i = 10;
int Obj::j = 12;

// 为上面的类实现一个容器
class ObjContainer {
private:
	vector<Obj*> a;
public:
	void add(Obj* obj) { a.push_back(obj); }
	friend class SmartPointer;
};

// 实现智能指针,用于访问类Obj的成员
class SmartPointer {
private:
	ObjContainer oc;
	int index;
public:
	SmartPointer(ObjContainer& objc) {
		oc = objc;
		index = 0;
	}
	// 返回值表示列表结束
	bool operator++() {// 前缀版本
		if (index >= oc.a.size() - 1以上是关于cpp►常见运算符的重载的主要内容,如果未能解决你的问题,请参考以下文章

使用重载的 >> 运算符调用 CPP 构造函数

c_cpp 带有重载运算符的模板

在cpp中重载<<运算符的正确方法是啥[重复]

c_cpp C ++中的运算符重载

c_cpp 重载调用运算符C ++

我想在cpp中实现python列表,但卡在重载下标运算符[]和逗号,[关闭]