手機網(wǎng)站開發(fā)書籍百度搜索引擎首頁
1.概念? ? ? ??
重載概念:
C++ 允許在同一作用域中的某個函數(shù)和運算符指定多個定義,分別稱為函數(shù)重載和運算符重載。
運算符重載概念:對已有的運算符重新進(jìn)行定義,賦予其另一種功能,以適應(yīng)不同的數(shù)據(jù)類型
這里主要介紹一下運算符重載。
重載大部分 C++ 內(nèi)置的運算符。這樣,您就能使用自定義類型的運算符
重載的運算符是帶有特殊名稱的函數(shù),函數(shù)名是由關(guān)鍵字 operator 和其后要重載的運算符符號構(gòu)成的。與其他函數(shù)一樣,重載運算符有一個返回類型和一個參數(shù)列表
????????大多數(shù)的重載運算符可被定義為普通的非成員函數(shù)或者被定義為類成員函數(shù)。如果我們定義上面的函數(shù)為類的非成員函數(shù),那么我們需要為每次操作傳遞兩個參數(shù),如下所示:
Person operator+(const Person& p1,const Person& p2)
? ? ? ? 如果是成員函數(shù),對象作為參數(shù)進(jìn)行傳遞,對象的屬性使用?this?運算符進(jìn)行訪問
//成員函數(shù)實現(xiàn) + 號運算符重載
Person operator+(const Person& p) {
Person temp;
temp.m_A = this->m_A + p.m_A;
temp.m_B = this->m_B + p.m_B;
return temp;
}
2.加號運算符重載
作用:
實現(xiàn)兩個自定義數(shù)據(jù)類型相加的運算
代碼
class Person {
public:
Person() {};
Person(int a, int b)
{
this->m_A = a;
this->m_B = b;
}
//成員函數(shù)實現(xiàn) + 號運算符重載
Person operator+(const Person& p) {
Person temp;
temp.m_A = this->m_A + p.m_A;
temp.m_B = this->m_B + p.m_B;
return temp;
}
public:
int m_A;
int m_B;
};
//全局函數(shù)實現(xiàn) + 號運算符重載
//Person operator+(const Person& p1, const Person& p2) {
// Person temp(0, 0);
// temp.m_A = p1.m_A + p2.m_A;
// temp.m_B = p1.m_B + p2.m_B;
// return temp;
//}
//運算符重載 可以發(fā)生函數(shù)重載
Person operator+(const Person& p2, int val)
{
Person temp;
temp.m_A = p2.m_A + val;
temp.m_B = p2.m_B + val;
return temp;
}
void test() {
Person p1(10, 10);
Person p2(20, 20);
//成員函數(shù)方式
Person p3 = p2 + p1; //相當(dāng)于 p2.operaor+(p1)
cout << "mA:" << p3.m_A << " mB:" << p3.m_B << endl;
Person p4 = p3 + 10; //相當(dāng)于 operator+(p3,10)
cout << "mA:" << p4.m_A << " mB:" << p4.m_B << endl;
}
int main() {
test();
system("pause");
return 0;
}
總結(jié)1:對于內(nèi)置的數(shù)據(jù)類型的表達(dá)式的的運算符是不可能改變的
總結(jié)2:不要濫用運算符重載
3.左移運算符重載
作用:可以輸出自定義數(shù)據(jù)類型
class Person {
friend ostream& operator<<(ostream& out, Person& p);
public:
Person(int a, int b)
{
this->m_A = a;
this->m_B = b;
}
//成員函數(shù) 實現(xiàn)不了 p << cout 不是我們想要的效果
//void operator<<(Person& p){
//}
private:
int m_A;
int m_B;
};
//全局函數(shù)實現(xiàn)左移重載
//ostream對象只能有一個
ostream& operator<<(ostream& out, Person& p) {
out << "a:" << p.m_A << " b:" << p.m_B;
return out;
}
void test() {
Person p1(10, 20);
cout << p1 << "hello world" << endl; //鏈?zhǔn)骄幊?}
int main() {
test();
system("pause");
return 0;
}
總結(jié):重載左移運算符配合友元可以實現(xiàn)輸出自定義數(shù)據(jù)類型
4.遞增運算符重載
作用: 通過重載遞增運算符,實現(xiàn)自己的整型數(shù)據(jù)
class MyInteger {
friend ostream& operator<<(ostream& out, MyInteger myint);
public:
MyInteger() {
m_Num = 0;
}
//前置++
MyInteger& operator++() {
//先++
m_Num++;
//再返回
return *this;
}
//后置++
MyInteger operator++(int) {
//先返回
MyInteger temp = *this; //記錄當(dāng)前本身的值,然后讓本身的值加1,但是返回的是以前的
值,達(dá)到先返回后++;
m_Num++;
return temp;
}
private:
int m_Num;
};
ostream& operator<<(ostream& out, MyInteger myint) {
out << myint.m_Num;
return out;
}
//前置++ 先++ 再返回
void test01() {
MyInteger myInt;
cout << ++myInt << endl;
cout << myInt << endl;
}
//后置++ 先返回 再++
void test02() {
MyInteger myInt;
cout << myInt++ << endl;
cout << myInt << endl;
}
int main() {
test01();
//test02();
system("pause");return 0;
}
總結(jié): 前置遞增返回引用,后置遞增返回值
5.賦值運算符重載
c++編譯器至少給一個類添加4個函數(shù)
1. 默認(rèn)構(gòu)造函數(shù)(無參,函數(shù)體為空)
2. 默認(rèn)析構(gòu)函數(shù)(無參,函數(shù)體為空)
3. 默認(rèn)拷貝構(gòu)造函數(shù),對屬性進(jìn)行值拷貝
4. 賦值運算符 operator=, 對屬性進(jìn)行值拷貝
如果類中有屬性指向堆區(qū),做賦值操作時也會出現(xiàn)深淺拷貝問題
避免淺拷貝問題:
那如果類中有屬性需要開辟堆空間,如果避免淺拷貝問題呢?
1. 需要定義拷貝構(gòu)造函數(shù)和賦值函數(shù)
2. 或者,就禁用這兩個函數(shù)(用private)
class Person
{
public:
Person(int age)
{
//將年齡數(shù)據(jù)開辟到堆區(qū)
m_Age = new int(age);
}
//重載賦值運算符
Person& operator=(Person &p)
{
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
//編譯器提供的代碼是淺拷貝
//m_Age = p.m_Age;
//提供深拷貝 解決淺拷貝的問題
m_Age = new int(*p.m_Age);
//返回自身
return *this;
}
~Person()
{
if (m_Age != NULL)
{
delete m_Age;
m_Age = NULL;
}
}
//年齡的指針
int *m_Age;
};
void test01()
{
Person p1(18);
Person p2(20);
Person p3(30);
p3 = p2 = p1; //賦值操作
cout << "p1的年齡為:" << *p1.m_Age << endl;
cout << "p2的年齡為:" << *p2.m_Age << endl;
cout << "p3的年齡為:" << *p3.m_Age << endl;
}
int main() {
test01();
//int a = 10;
//int b = 20;
//int c = 30;
//c = b = a;
//cout << "a = " << a << endl;
//cout << "b = " << b << endl;
//cout << "c = " << c << endl;
system("pause");
return 0;
}
6.關(guān)系運算符重載
作用:
重載關(guān)系運算符,可以讓兩個自定義類型對象進(jìn)行對比操作
代碼
#include <iostream>
#include <string>
using namespace std;
class Person
{public:Person(const string& name, int age){this->m_Name = name;this->m_Age = age;};bool operator==(const Person& p){return (this->m_Name == p.m_Name && this->m_Age == p.m_Age);}bool operator!=(const Person & p){return !(this->m_Name == p.m_Name && this->m_Age == p.m_Age);}private:string m_Name;int m_Age;
};
void test01()
{Person a("孫悟空", 18);Person b("孫悟空", 18);if (a == b){cout << "a和b相等" << endl;}else{cout << "a和b不相等" << endl;}if (a != b){cout << "a和b不相等" << endl;}else{cout << "a和b相等" << endl;}
}
int main() {test01();// system("pause");getchar();return 0;
}
7.函數(shù)調(diào)用運算符重載
- 函數(shù)調(diào)用運算符 () 也可以重載
- 由于重載后使用的方式非常像函數(shù)的調(diào)用,因此稱為仿函數(shù)
- 仿函數(shù)沒有固定寫法,非常靈活
class MyPrint
{public:void operator()(string text){cout << text << endl;}
};
void test01()
{//重載的()操作符 也稱為仿函數(shù)MyPrint myFunc;myFunc("hello world");
}
class MyAdd
{public:int operator()(int v1, int v2){return v1 + v2;}
};
void test02()
{MyAdd add;int ret = add(10, 10);cout << "ret = " << ret << endl;//匿名對象調(diào)用cout << "MyAdd()(100,100) = " << MyAdd()(100, 100) << endl;
}
int main() {test01();test02();system("pause");return 0;
}