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►常见运算符的重载的主要内容,如果未能解决你的问题,请参考以下文章