網站首頁 編程語言 正文
賦值運算符重載
在C++中基本數據類型例如整型,可以實現連續賦值:a=b=c;而我們的對象的成員屬性雖然可以相等,但是如果牽扯到堆地址,就會有深淺拷貝的問題存在。所以我們自己重載賦值運算符,實現連等的方法。
類結構
class Info
{
int* m_a;
public:
Info()
{
m_a = NULL;
}
Info(int a)
{
m_a = new int(a);
}
~Info()
{
if (m_a != NULL)
delete m_a;
m_a = NULL;
}
};
創建一個Info類,定義指針屬性*m_a, 然后自己定義Info類的無參、有參構造函數和析構函數,再給屬性賦值的時候,是用new關鍵字開辟堆區并存放數據;析構在前面的文章中講到了他的作用,就是在程序結束前編譯器自動調用析構來完成對象的清理工作,在這里就會把堆區的數據釋放掉。
問題的出現
Info f(20);
Info f1;
Info f2;
Info f3(30);
f1 = f2 =f;
直接連等是不行的,因為在析構函數里訪問了一個NULL地址,就比如程序即將結束,f調用析構函數,刪除m_a指向的地址,然而f1也會調用析構函數,由于f1和f的m_a指向同一個地址,那就好重復訪問,訪問一個被刪除的地址肯定會報錯的;因此我們需要對賦值運算符進行重載,這里提示一下,連等就相當于鏈式調用,因此重載運算符的返回值類型需要返回引用。
具體實現
Info& operator=(Info& f)
{
if (m_a != NULL)
delete m_a;
m_a = NULL;
m_a = new int(*f.m_a);
return *this;
}
返回值類型是類引用,這樣可以做到鏈式調用 ,函數名還是統一的operator+運算符,既然是賦值運算符就用operator=,然后這個重載發生在成員內部,因此參數里只需要傳入用來賦值的對象即可,注意倒數第二行代碼,我利用new讓m_a指向堆區中新開辟的地址,這是賦值運算符重載的關鍵;就是因為把地址指向了堆區的新地址,這樣不同的對象在調用析構函數的時候各刪各的堆地址,不會訪問空地址,這個問題的解決和深淺拷貝的解決方式一樣,都是自己寫方法來避免原來方法中成員屬性指向同一個地址。最后返回自身的引用,就可以實現連續調用了。
關系運算符重載
關系運算符有“大于”、“小于”、“等于”、“大于等于”、“不等于”等幾種情況,我就舉例等于和不等于兩種賦值運算符重載的例子
類結構
class Info
{
friend void test1();
int* m_a;
string m_name;
public:
Info()
{
m_a = NULL;
}
Info(int a,string name)
{
m_a = new int(a);
m_name = name;
}
~Info()
{
if (m_a != NULL)
delete m_a;
m_a = NULL;
}
}
這里的類結構相比于賦值運算符重載多了一個String類型的m_name屬性,然后寫出類的無參、有參構造和析構函數,最上面的friend關鍵字是加了一個友元的聲明,讓下面的test1函數可以訪問類的私有屬性。
具體實現
bool operator==(Info& f)
{
if (*this->m_a == *f.m_a && m_name==f.m_name)
return true;
else return false;
}
bool operator!=(Info& f)
{
if (*this->m_a == *f.m_a && m_name == f.m_name)
return false;
else return true;
}
返回值類型寫成布爾類型,因為關系運算的結果就是布爾類型的,常和while循環以及if語句使用;函數名還是老樣子,operator==和operator!=,分別是相等和不等;既然是成員內部的關系運算符重載,那么形參傳入一個待比較對象即可。
調用方法
void test1()
{
Info f1(20,"張三");
Info f3(30,"張六");
if (f1== f3) cout << "二者相等" << endl;
else if (f1!= f3) cout << "二者不相等" << endl;
}
運行效果?
函數調用運算符重載
函數調用使用“()”,函數調用也是可以重載的,而且重載的調用很像直接調用函數,因此也叫做仿函數。
類結構
class MyHello
{
public:
string hello;
};
非常簡單的類結構,只有一個公有權限下的String類型的hello屬性。
具體實現
void operator()(string s)
{
cout << s << endl;
}
因為只是打印一下,不需要返回值,函數名不多說了,和前面類似,然后傳入字符串類型再方法里打印出來。
調用方法?
void test()
{
MyHello hello;
hello("Hello World");
}
首先創建類對象hello,直接使用重載后的調用方法:對象+(字符串);這樣就能打印出引號里的內容了:
匿名對象調用
最后補充一個匿名對象的知識,示例:
class MyAdd
{
public:
int operator()(int num1, int num2)
{
return num1 + num2;
}
};
void test1()
{
MyAdd myAdd;
int num = myAdd(160, 40);
cout << "ret =" << myAdd(160,40) << endl;
cout << "ret =" << MyAdd()(100,50) << endl;
}
這里我寫了一個只有重載函數調用函數的類,并在test1中用常規和匿名對象調用重載后的函數調用方法;看一下運行效果:
先創建對象,再通過對象調用函數的方法我們不感到奇怪,但是最后一個輸出語句中,MyAdd()(100,50)是什么意思呢 ,這就是匿名對象,往后我們遇到形如類名+()再+調用函數的方式,那就是創建了匿名對象,其特點就是創建完畢后就會刪除,這里我們只都一下數據,所以適合匿名對象的調用。
總結
到這里C++的運算符重載徹底結束了,運算符重載可以多個都重載并互相配合使用,把對象的屬性可以和基本類型一樣進行算數運算和邏輯運算,在類對象比較多的時候可以節省很多時間,簡化程序。
原文鏈接:https://blog.csdn.net/m0_58618795/article/details/125250061
相關推薦
- 2022-03-06 C語言之快速排序算法(遞歸Hoare版)介紹_C 語言
- 2022-09-20 Python中類的mro與繼承關系詳解_python
- 2022-12-15 C++異步數據交換實現方法介紹_C 語言
- 2022-07-14 Matlab實現灰色預測的示例代碼_C 語言
- 2022-07-28 C++實例講解引用的使用_C 語言
- 2022-05-06 python畫圖時給圖中的點加標簽和plt.text的使用_python
- 2022-11-03 C#如何給新建的winform程序添加資源文件夾Resources_C#教程
- 2022-06-09 教你在k8s上部署HADOOP-3.2.2(HDFS)的方法_云其它
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支