内容纲要
123讲,递增运算符的重载、赋值运算符的重载、关系运算符重载、函数调用运算符重载
递增运算符重载++
注意传参类型和返回类型,以及要留意传参是传引用还是对象。
#include <iostream>
#include "string"
using namespace std;
class Integer {
friend std::ostream& operator<< (std::ostream& out, Integer integer);
public:
Integer() {
m_Num = 0;
}
//重载前置++运算符
Integer& operator++ () {
m_Num++;
return *this;
};
//重载后置++运算符
Integer operator++(int) {
Integer integer = *this;
m_Num++;
return integer;
}
private:
int m_Num;
};
//std::ostream& operator<< (std::ostream& out,Integer& integer) {//下面<< 重载的时候这里不去掉&符号就会报错。
std::ostream& operator<< (std::ostream& out,Integer integer) {//注意这里右边那个Integer 的&符号要去掉。。不然上方代码会报错
out << integer.m_Num;
return out;
}
void test1() {
Integer myInteger;
cout << ++myInteger << std::endl;
cout << myInteger << endl;
}
void main() {
test1();
}
pay attention:
注意! 返回的时候返回引用类型是可以修改原始数据的。
前置++如果返回的是 MyInteger类型则会自动调用拷贝构造函数,则不能修改原始数据。
总结:前置递增返回的是引用,后置递增返回的是值。
TIP:后置递增/递减 不能做左值。所以可以返回的是值。
值得留意重载<< 运算符的时候要注意,在重载自增的时候能否放进去对象或者地址。。。
赋值运算符重载
//案例代码:这里模拟浅拷贝时候出现的问题,分析在代码后面。
#include <iostream>
#include"string"
using namespace std;
class Person {
public:
Person(int age) {
m_Age = new int(age);
}
~Person() { //调用析构函数,堆区分配的内存由程序员手动释放
if (m_Age != NULL) {
delete m_Age;
m_Age = NULL;
}
}
//void operator=(Person &p) {
//
// /*
// 编译器提供的浅拷贝,在析构释放内存的时候会崩溃。原因参考后面的代码注释
// m_Age = p.m_Age;
// */
// //先判断原来的对象是否有属性在堆区,如果有,请先释放干净!!!
// if (this->m_Age != NULL) { //这里的this 可以不用写,因为编译器默认的是自己的指针。
// delete m_Age;
// m_Age = NULL;
// }
// this->m_Age = new int(*p.m_Age); //在堆区分配内存空间。我认为这里的this指的是左值。
//}// 如果要连续赋值,则可以在这里返回一个自己的对象。
int * m_Age;
};
void main() {
Person p1(18);
cout << p1.m_Age << endl;
Person p2(20);
cout << p2.m_Age << endl;
p2 = p1;
system("pause");// 这段代码之后程序会崩溃,
//因为属于浅拷贝,p1 p2 指向同一块堆中内存。如果析构则会崩溃,
//解决办法,重载= 赋值运算符。
}
分析1:由于p1 = p2; 编译器会自动调用浅拷贝,属于值拷贝,并没有在堆中分配新的内存,而是两个对象指向同一个内存地址,不析构暂时不会报错,但是析构之后呢?
分析2:会报错,p1 或者p2 其中有一个先调用析构函数,销毁掉了在堆中创建的内存,导致另外一个对象析构的时候找不到内存,程序崩溃。
使用重载= 运算符实现深拷贝。
Talk is cheap,show me the code!!!
void operator=(Person &p) {
/*
编译器提供的浅拷贝,在析构释放内存的时候会崩溃。原因参考后面的代码注释
m_Age = p.m_Age;
*/
//先判断原来的对象是否有属性在堆区,如果有,请先释放干净!!!
if (this->m_Age != NULL) { //这里的this 可以不用写,因为编译器默认的是自己的指针。
delete m_Age;
m_Age = NULL;
}
this->m_Age = new int(*p.m_Age); //在堆区分配内存空间。我认为这里的this指的是左值。
}// 如果要连续赋值,则可以在这里返回一个自己的对象。
关系运算符重载
emmm 笔记没什么好些的。和前面依葫芦画瓢
#include<iostream>
#include"string"
using namespace std;
class Person {
public:
string operator=(Person& p) {
string res = (this->m_Age == p.m_Age) && (this->m_Name == p.m_Name) ? "是同一个人" : "不是同一个人";
return res;
}
int m_Age;
string m_Name;
};
void test01() {
Person p1 = {18 , "Tom"};
Person p2 = {18 , "Tom"};
//Person p2 = {20,"jerry"};
bool test;
cout << "P1 对象是否等于P2 对象? " << (p1 = p2) << endl;
}
void main() {
test01();
}
函数调用运算符重载
仿函数()();后面STL要用到,这里的笔记要认真写一下。
#include <iostream>
#include "string"
using namespace std;
class Person {
public:
int operator()(Person p1) {
return p1.m_Age + this->m_Age;
}
string m_Name;
int m_Age;
};
void test() {
Person p1 = {"张麻子",18};
Person p2 = {"张三",20};
Person p3;
p3.m_Age = 10;
int res = p3(p2);
cout << "res 的值为:" << res << endl;
}
void main() {test();}
注意这里的:匿名对象知识点!!!!
匿名对象: 类名 ( )( 参数1,参数2, ...)