加号运算符重载
自定义数据类型实现运算
在成员函数 或者 全局函数 中重写一个+运算符的函数
函数名 operator+()
运算符重载也可以提供多个版本:Person p4 = p3+10;
//加号运算符重载
//自定义数据类型也可以实现一个加号运算
class Person
{
public:
Person()
{
}
Person(int a, int b) :m_A(a), m_B(b)
{}
//+运算符重载,成员函数
Person operator+(Person &p) //二元函数
{
Person tmp;
tmp.m_A = this->m_A + p.m_A;
tmp.m_B = this->m_B + p.m_B;
return tmp;
}
int m_A;
int m_B;
};
//+运算符重载, 全局函数
Person operator+(Person &p1, Person &p2) //二元函数
{
Person tmp;
tmp.m_A = p1.m_A + p2.m_A;
tmp.m_B = p1.m_B + p2.m_B;
return tmp;
}
void test02()
{
Person p1(10, 10);
Person p2(10, 10);
//p3 = p1 + p2
Person p3 = p1 + p2; //直接这样写会出现 没有与这些操作数匹配的运算符
/*------------解决这个问题就是在类里面加一个重载Person operator+(Person &p)------------*/
}
左移运算符重载
不要随意使用符号重载,内置数据类型(int, float等)的运算符是不可以重载的
左移运算符重载不能写道成员函数中,要写到全局函数中
函数名 operator<<()
//左移运算符重载
class Person1
{
public:
friend ostream &operator<<(ostream &cout, Person1 &p);
Person1(int a, int b)
{
this->m_A = a;
this->m_B = b;
}
private:
int m_A;
int m_B;
};
ostream &operator<<(ostream &cout, Person1 &p) //把它作为友元函数,就可以调用私有属性
{
cout << "m_A = " << p.m_A << ", m_B = " << p.m_B;
return cout;
}
void test03()
{
Person1 p1(10, 10);
cout << p1 << endl; //直接写会出现没有与操作数匹配的运算符<<
/*--------------解决方法是实现左移运算符重载,但是重载左移不能写到成员函数中--------------*/
}
前置后置递增递减运算符重载
优先使用前置,前置比后置效率更高,因为后置需要创建一个变量
class MyInteger
{
public:
MyInteger()
{
m_Num = 0;
}
//前置++重载
MyInteger& operator++()
{
this->m_Num++;
return *this;
}
//后置++重载, 用占位参数区分前置还是后置
MyInteger operator++(int)
{
MyInteger tmp = *this; //先保存下临时的值
m_Num++;
return tmp;
}
int m_Num;
};
ostream &operator<<(ostream &cout, MyInteger &myInt)
{
cout << myInt.m_Num;
return cout;
}
void test04()
{
MyInteger num;
cout << ++num << endl;
cout << num++ << endl;
cout << num << endl;
}
指针运算符重载(智能指针)
用来维护一个自定义类型的对象指针,让对象进行自动释放
为了让智能指针和一般的指针一样用->和*,因此需要重载->和*。
//指针运算符重载(智能指针)
//用来托管自定义类型的对象,让对象进行自动释放
class Person2
{
public:
Person2(int age)
{
this->Age = age;
}
void showAge()
{
cout << "年龄为:" << this->Age << endl;
}
~Person2()
{
cout << "调用析构函数" << endl;
}
int Age;
};
class smartPointer
{
public:
smartPointer(Person2 *person)
{
this->person = person;
}
//重载智能指针,使得sp->showAge()
Person2* operator->()
{
return this->person;
}
Person2& operator*()
{
return *this->person;
}
~smartPointer()
{
cout << "智能指针析构" << endl;
if (this->person != NULL)
{
delete this->person;
this->person = NULL;
}
}
private:
Person2 *person;
};
void test05()
{
//Person2 p1(10);//自动会析构,因为开辟到了栈上
//Person2 *p2 = new Person2(10); //不会自动析构,因为开辟在堆上,因此要用delete
//delete p2;
smartPointer sp(new Person2(10));
sp->showAge(); //本来应该是sp->sp->showAge();这是编译器对其进行了优化
(*sp).showAge();
}
赋值运算符重载
系统默认给类提供了一个简单的赋值运算符重载,简单值拷贝
导致如果类中有指向堆区的指针(char *name),就可能会出现深浅拷贝的问题,所以要重载=运算符
如果想链式编程,就return *this
//赋值运算符重载
//一个类默认创建:默认构造、析构、拷贝构造、operator=赋值运算符(进行简单的值传递)
class Person3
{
public:
Person3(int a)
{
this->m_A = a;
}
int m_A;
};
class Person4
{
public:
Person4(const char *name)
{
this->pName = new char[strlen(name) + 1];
strcpy(this->pName, name);
}
Person4& operator=(const Person4& p)
{
//先判断 如果原来已经堆区有内容,先释放
if (this->pName != NULL)
{
delete[] this->pName;
this->pName = NULL;
}
this->pName = new char[strlen(p.pName) + 1];
strcpy(this->pName, p.pName);
return *this;
}
~Person4()
{
if (this->pName != NULL)
{
delete[] this->pName;
this->pName = NULL;
}
}
char *pName;
};
void test06()
{
//Person3类中只有简单的默认赋值运算符
Person3 p(10);
Person3 p1(0);
p1 = p;
cout << "p1.m_A = " << p1.m_A << endl; //10
Person4 p2("张三");
Person4 p3("李四");
Person4 p5("老王");
//p3 = p2; //直接这样写的话就会出现浅拷贝的问题,因为指向同一空间,因此析构完p2后,析构p3会出现中断
cout << "p2.name = " << p2.pName << endl;
/* 出现上面错误的关键问题就是=赋值运算符太简单了,解决上面的问题就在类里面写一个=重载运算符 */
p5 = p3 = p2;
cout << "p5.name = " << p5.pName << endl;
}
[ ]运算符重载
int& MyArray::operator[] (int index)
函数调用运算符重载
class MyPrint
{
public:
void operator()()
{
cout << "Hello world!" << endl;
}
void operator()(string text)
{
cout << text << endl;
}
};
void test08()
{
MyPrint myPrint;
myPrint(); //仿函数,不是一个函数,是一个类下面的对象,只是里面的操作跟函数差不多
myPrint("你好");
}
不能重载 && 和 || 运算符
因为会失去它们原有的短路特性