内容汇总
#include <iostream>
using namespace std;
class A {
//友元函数,类外函数访问私有变量
//friend A operator-(const A& c1, const A& c2);
//friend A& operator+=(A& c1, const A& c2);
//friend A& operator++(A& c);//++a
//friend A operator++(A& c, int);//a++
//重载<<和>>最好在类外
friend ostream& operator<<(ostream& os, A& c);
friend istream& operator>>(istream& is, A& c);
private:
int a;
int b;
public:
A(int a = 0, int b = 0) :a(a), b(b) {}
void print() {
cout << a << "+" << b << endl;
}
//类内重载-
A operator-(const A& another) {
A c((this->a) - another.a, (this->b) - another.b);
return c;
}
//类内重载+
A operator+(const A& another) {
A c((this->a) + another.a, (this->b) + another.b);
return c;
}
//类内重载+=
A& operator+=(const A& another) {
(*this).a += another.a;
(*this).b += another.b;
return (*this);
}
//类内重载++a
A& operator++() {
(*this).a++;
(*this).b++;
return (*this);
}
//类内重载a++,需要默认参数,此处不需要返回&
A operator++(int) {
A tmp = (*this);
(*this).a++;
(*this).b++;
return tmp;
}
//类内重载=
A& operator=(const A& c) {
if (this == &c)
return (*this);
(*this).a = c.a;
(*this).b = c.b;
return (*this);
}
};
类外重载-
//A operator-(const A& c1, const A& c2) {
// A c(c1.a - c2.a, c1.b - c2.b);
// return c;
//}
类外重载+
//A operator-(const A& c1, const A& c2) {
// A c(c1.a + c2.a, c1.b + c2.b);
// return c;
//}
类外重载+=
//A& operator+=(A& c1,const A& c2) {
// c1.a += c2.a;
// c1.b += c2.b;
// return c1;
//}
类外重载++a
//A& operator++(A& c) {
// c.a++;
// c.b++;
// return c;
//}
类外重载a++
//A operator++(A& c,int) {
// A tmp = c;
// c.a++;
// c.b++;
// return tmp;
//}
//<<和>>最好类外重载
ostream& operator<<(ostream& os, A& c) {
os << c.a << '+' << c.b;
return os;
}
istream& operator>>(istream& is, A& c) {
is >> c.a >> c.b;
return is;
}
int main() {
A c1(1, 1), c2(2, 2), c3;
cin >> c3;
cout << c3 << endl;
}
一.来源
假设,现在有类A:
class A {
public:
A(int a) {
this->a = a;
}
private:
int a;
};
定义:
A a1(1), a2(2);
现在我想直接执行两个类的相加a1+a2,但是C++没有这种方法,所以引出操作符重载。
二.实现
现在实现两个虚数相加:(1+2i)+(3+4i).
先看2种普通实现方法:
方法一:
class Complex {
friend Complex complexadd(Complex& c1, Complex& c2);//定义友元函数
public:
Complex(int a,int b) {
this->a = a;
this->b = b;
}
void printComplex() {
cout << "(" << this->a << "," << this->b << "i)" << endl;
}
private:
int a;//实数
int b;//虚数
};
//相加
Complex complexadd(Complex& c1, Complex& c2) {
Complex c3(c1.a + c2.a, c1.b + c2.b);
return c3;
}
int main() {
Complex a1(1,2), a2(3,4);
a1.printComplex();
a2.printComplex();
Complex c3 = complexadd(a1, a2);
c3.printComplex();
}
方法二:
class Complex {
public:
Complex(int a,int b) {
this->a = a;
this->b = b;
}
void printComplex() {
cout << "(" << this->a << "," << this->b << "i)" << endl;
}
Complex addcomplex(const Complex& another) {
Complex a3(this->a + another.a, this->b + another.b);
return a3;
}
private:
int a;//实数
int b;//虚数
};
int main() {
Complex a1(1,2), a2(3,4);
a1.printComplex();
a2.printComplex();
Complex a3=a2.addcomplex(a1);
a3.printComplex();
}
操作符重载方法:
方法一:操作符重载写在全局
class Complex {
friend Complex operator+(Complex& a1, Complex& a2);//申明友元函数
public:
Complex(int a,int b) {
this->a = a;
this->b = b;
}
void printComplex() {
cout << "(" << this->a << "," << this->b << "i)" << endl;
}
private:
int a;//实数
int b;//虚数
};
//操作符重载写在全局
Complex operator+(Complex& a1, Complex& a2) {
Complex a3(a1.a + a2.a, a1.b + a2.b);
return a3;
}
int main() {
Complex a1(1,2), a2(3,4);
a1.printComplex();
a2.printComplex();
//此处可以直接实现加法!等价于Complex a3 = operator(a1,a2);
Complex a3 = a1 + a2;
a3.printComplex();
}
方法二:操作符重载写在局部
class Complex {
public:
Complex(int a,int b) {
this->a = a;
this->b = b;
}
void printComplex() {
cout << "(" << this->a << "," << this->b << "i)" << endl;
}
//操作符重载写在局部
Complex operator+(Complex& another) {
Complex a3(this->a + another.a, this->b + another.b);
return a3;
}
private:
int a;//实数
int b;//虚数
};
int main() {
Complex a1(1,2), a2(3,4);
a1.printComplex();
a2.printComplex();
//此处可以直接实现加法!
Complex a3 = a1 + a2;
//等价
Complex a4 = a1.operator+(a2);
a3.printComplex();
a4.printComplex();
}
三.注意事项
1.记住不能重载的,其他都可以重载。
:: | . |
---|---|
.* | ?* |
sizeof | typeid |
2.不能创造重载。例如:a1 666 a2。自己创造一个666运算。
3.重载不能改变运算符的优先级别。
4.重载不能改变运算符的结合性。
5.重载运算符的函数不能有默认参数。
7.=, ->, [], ()不可以是全局域中的重载(即不能重载为友员函数)
1.重载减号(-)
class A {
friend A operator-(const A& c1, const A& c2);//申明友元函数
private:
int a;//实部
int b;//虚部
public:
A(int a, int b) {
this->a = a;
this->b = b;
}
void print() {
cout << "(" << a << "+" << b << "i)" << endl;
}
//操作符重载类内定义
A operator-(const A& another) {
A c(this->a - another.a, this->b - another.b);
return c;
}
};
//操作符重载外部定义
//A operator-(const A& c1, const A& c2) {
// A c(c1.a - c2.a, c1.b - c2.b);
// return c;
//}
int main() {
A c1(3, 4), c2(1, 2);
A c = c1 - c2 - c2;
c.print();
}
2.+=号重载
class A {
//friend A& operator+=(A& c1, A c2);//友元函数声明
private:
int a;//实部
int b;//虚部
public:
A(int a, int b) {
this->a = a;
this->b = b;
}
void print() {
cout << "(" << a << "+" << b << "i)" << endl;
}
//"+="操作符重载类内定义
A &operator+=( A& another) {
this->a += another.a;
this->b += another.b;
return *this;
}
};
//“+=”操作符重载外部定义
/*A& operator+=(A& c1, A c2) {
c1.a += c2.a;
c1.b += c2.b;
return c1;
}*/
int main() {
A c1(3, 4), c2(1, 2);
c1 += c2;
c1.print();
}
3.++a重载
class A {
//friend A& operator++(A& c);//友元函数声明
private:
int a;//实部
int b;//虚部
public:
A(int a, int b) {
this->a = a;
this->b = b;
}
void print() {
cout << "(" << a << "+" << b << "i)" << endl;
}
//"++"操作符重载类内定义
A & operator++( ) {
this->a++;
this->b++;
return *this;
}
};
//“++”操作符重载外部定义
/*A& operator++(A& c) {
c.a++;
c.b++;
return c;
}*/
int main() {
A c1(3, 4), c2(1, 2);
++c1;
c1.print();
}
4.a++重载
这里是C++一个坑,用没有意义的占位参数,标识是后++。
class A {
//friend A& operator++(A& c,int);//友元函数声明
private:
int a;//实部
int b;//虚部
public:
A(int a, int b) {
this->a = a;
this->b = b;
}
inline void print() {
cout << "(" << a << "+" << b << "i)" << endl;
}
//"++a"操作符重载类内定义
A& operator++( ) {
this->a++;
this->b++;
return *this;
}
//"a++"操作符重载类内定义
A operator++( int ) {//此处不能用const A&,因为temp在函数运行完成后被释放,此处不必返回&
A temp=*this;//用一个临时变量
this->a++;
this->b++;
/*
++(*this);//或者直接调用++a,代替上面两步,更爽!
*/
return temp;
}
};
#if 0
//“a++”操作符重载外部定义
A operator++(A& c, int) //int为占位参数,用来标识后++,此处返回值不必为&
{
A temp=c;
c.a++; c.b++;
return temp;
}
#endif // 0
int main() {
A c1(3, 4), c2(1, 2);
c1++;
c1.print();
}
5.为什么这里都用&引用
A& operator++(A& c)
如果不用引用,就无法实现连加,目的还是为了防止函数执行完后返回的匿名对象被释放掉,后面就无法访问其值。
为什么a++,不必返回引用呢?因为即使返回引用,得到的值,也只是第一次++后的值。因为后++返回的是temp,不是*this。
前++返回当前对象,离开这个函数后,当前对象依然存在,因此可以返回引用;后++返回是一个局部对象,离开函数就被消亡,因此不能返回引用! 看下面例子也能明白。
6.<<左移操作符重载
作用:实现直接输出类中变量的值。
查看cout类型:鼠标放在cout上,右键点击转到定义。
实现:
class A {
//friend ostream& operator<<(ostream& os, A& t);//友元函数申明
private:
int a;
int b;
public:
A(int a, int b) {
this->a = a;
this->b = b;
}
//类内重载
ostream& operator<<(ostream& os) {
os << "a=" << this->a << ",b=" << this->b << endl;
return os;
}
};
//重载外部定义
/*ostream& operator<<(ostream& os, A& t) {
os << "a=" << t.a << ",b=" << t.b << endl;
return os;
}*/
int main(int argc, char** argv)
{
A t1(1, 2);
t1 << cout;//类内重载,写法很奇怪
//cout << t1 << endl;//类外重载
}
注意:为什么ostream& operator<<(ostream& os, A& t),返回是ostream。
int a = 1;
int b = 2;
int c = 3;
cout << a << b << c << endl;
因为cout<<a,返回值是cout,然后才能继续输出后面cout<<b,cout<<c<<endl;
7.>>右移操作符重载
class A {
friend istream& operator>>(istream& in, A& t1);//友元函数申明
private:
int a;
int b;
public:
A() {
this->a = 0;
this->b = 0;
}
~A() {
cout << "a=" << this->a << ",b=" << b << endl;
}
};
//重载外部定义
istream& operator>>(istream& is, A& t1) {
is >> t1.a;
is >> t1.b;
return is;
}
int main(int argc, char** argv)
{
A t1;
cin >> t1;
}
8.=操作符重载
class Student
{
public:
Student() {
this->id = 0;
this->name = nullptr;
}
//拷贝构造
Student(int id, char* name) {
this->id = id;
//对*name一定要申请空间,否则浅拷贝,数据不安全。
int len = strlen(name);//判断字符数组长度,用strlen,不是size、sizeof
this->name = new char[len+1];//+1是为了预留一个'\0'
strcpy_s(this->name,len+1, name);
}
//深拷贝构造
Student(const Student& s) {
this->id = s.id;
this->name = new char[strlen(s.name)+1];
strcpy_s(this->name, strlen(s.name) + 1,s.name);
}
~Student() {
if (this->name != nullptr) {
delete[] this->name;
this->name = nullptr;
this->id = 0;
}
}
void print() {
cout << "id=" << this->id << ",name=" << this->name << endl;
}
//"="操作符重载
Student& operator=(Student& s) {
//1.s=s,直接返回本身。
if (this == &s)
return *this;
//2.先将原来空间释放掉
if (this->name != nullptr) {
delete[] this->name;
this->name = nullptr;
this->id = 0;
}
//3.执行深拷贝
this->id = s.id;
this->name = new char[strlen(s.name) + 1];
strcpy_s(this->name, strlen(s.name) + 1, s.name);
return *this;
}
private:
int id;
char* name;
};
int main() {
char name1[64] = "abc";
Student s1(1, name1);
//在这里等号实际上为拷贝构造,等价于s2(s1);
Student s2=s1;
s2.print();
char name2[64] = "def";
//“=”操作符重载
Student s3(2, name2);
s2 = s3;
s2.print();
}
9.重载小括号()
class Sqr
{
public:
Sqr(int a) {
this->a = a;
}
//重载小括号“()”
int operator()(int b) {
return b * b;
}
int operator()(int b, int c) {
return b * c;
}
private:
int a;
};
int main() {
Sqr s1(1);
//s1(2)将对象当成一个普通函数来调用,称这种对象是仿函数或伪函数
int value1=s1(2);
cout << value1 << endl;
int value2 = s1(3, 4);
}
10.new和delete重载
void和void之间没有任何关系,void是一个万能指针。
使用new可以触发类的构造函数,使用delete会触发类的析构函数。
class A
{
public:
A(int a) {
cout << "调用了有参构造函数" << endl;
this->a = a;
}
void print() {
cout << "a=" << a << endl;
}
//new操作符重载,void*返回一个万能指针,size_t是申请内存大小
//重载的new操作符,依然会触发对象的构造函数
void* operator new(size_t size) {
cout << "重载了new操作符" << endl;
return malloc(size);
}
void operator delete(void* p) {
cout << "重载了delete操作符" << endl;
if (p != nullptr) {
free(p);
p = nullptr;
}
}
~A() {
cout << "触发了析构函数" << endl;
}
private:
int a;
};
int main() {
//等价于ap->operator new(sizeof(A));这里的10会触发构造函数
A* ap = new A(10);
ap->print();
delete ap;
}
结果:
11.[ ]重载
class A
{
public:
A() {
this->a = 0;
}
A(int a) {
cout << "调用了有参构造函数" << endl;
this->a = a;
}
void print() {
cout << "a=" << a << endl;
}
//new操作符重载,void*返回一个万能指针,size_t是申请内存大小
//重载的new操作符,依然会触发对象的构造函数
void* operator new[](size_t size) {
cout << "重载了new[]操作符" << endl;
return malloc(size);
}
void operator delete[](void* p) {
cout << "重载了delete操作符" << endl;
if (p != nullptr) {
free(p);
p = nullptr;
}
}
~A() {
cout << "触发了析构函数" << endl;
}
private:
int a;
};
int main() {
//触发无参构造,实际上申请空间大小sizeof(A)*10
A* ap = new A[10];
ap->print();
//触发10次void operator delete[](void* p)
delete[] ap;
}
结果:
12.&&和| |重载(不建议重载这两个)
首先看以下代码:
int a = 0;
if (a && (a = 10)) {//在这里a=10被短路了,没有执行。
}
cout << "a=" << a << endl;
结果:
实现&&重载代码:
class Test {
private:
int value;
public:
Test(int value) {
this->value = value;
}
//重载&&
bool operator&&(Test& another) {
cout << "执行了&&操作符重载!" << endl;
if ( this->value&&another.value)
{
return true;
}
else {
return false;
}
}
};
int main() {
Test t1(10), t2(20);
if (t1 && t2) {//t1.operator&&(t2)
cout << "t1和t2都不为空" << endl;
}
else {
cout << "t1或t2为空" << endl;
}
}
结果:
class Test {
private:
int value;
public:
Test(int value) {
this->value = value;
}
/*~Test() {
cout << "value=" << value << endl;
}*/
//重载&&
void print() {
cout << "value=" << value << endl;
}
bool operator||(Test& another) {
cout << "执行了&&操作符重载!" << endl;
if ( this->value||another.value)
{
return true;
}
else {
return false;
}
}
//重载+
Test& operator+(Test& another) {
this->value += another.value;
return *this;
}
};
int main() {
Test t1(0), t2(20);
if (t1 || t2) {
cout << "t1或t2不为0" << endl;
}
else {
cout << "t1和t2都为0!" << endl;
}
}
结果:
13.强制类型转换
class boolean {
//输出,false输出false,true输出true
friend ostream& operator<<(ostream& os, const boolean& b);
friend istream& operator>>(istream& is, boolean& b);
private:
bool data;
public:
boolean(const bool d = false) :data(d) {}
~boolean() {}
//强制类型转换:实现(int)boolean或int(boolean)输出1或0
operator int() const { return (data ? 1 : 0); }
};
#include "boolean.h"
ostream& operator<<(ostream& os, const boolean& b) {
os << (b.data == true ? "true" : "false");
return os;
}
istream& operator>>(istream& is, boolean& b) {
string tmp;
is >> tmp;
b.data = (tmp == "true" ? true : false);
return is;
}
int main() {
boolean b(true);
cout << (int)b << endl;//此处使用强制类型转换
cout << int(b) << endl;//同上
}
}