C++之運算符重載(下)

4.提高

1.運算符重載機制
編譯器實現運算符重載實際上就是通過函數重載實現的,可分為全局函數方式,也可分為成員函數方式進行重載,并沒有改變原操作符的屬性和語義。只是針對某個特定類定義一種新的數據類型操作。
2.重載賦值運算符


  • 賦值運算符重載用于對象數據的復制
  • operator= 必須重載為成員函數
  • 重載函數原型為:
    類型 & 類名 :: operator= ( const 類名 & ) ;

結論:
1 先釋放舊的內存
2 返回一個引用
3 =操作符 從右向左
#define  _CRT_SECURE_NO_WARNINGS 
#include <iostream>
using namespace std;//class  Name
{
public:Name(const char *myp){m_len = strlen(myp);m_p =(char *) malloc(m_len + 1); //strcpy(m_p, myp);}//Name obj2 = obj1;//解決方案: 手工的編寫拷貝構造函數 使用深copyName(const Name& obj1){m_len = obj1.m_len;m_p = (char *)malloc(m_len + 1);strcpy(m_p, obj1.m_p);}//obj3 = obj1;  // C++編譯器提供的 等號操作 也屬 淺拷貝//obj3.operator=(obj1)Name& operator=(Name &obj1){//先釋放舊的內存if (this->m_p != NULL){delete[] m_p;m_len = 0;}//2 根據obj1分配內存大小this->m_len = obj1.m_len;this->m_p = new char [m_len+1];//把obj1賦值strcpy(m_p, obj1.m_p);return *this;}~Name(){if (m_p != NULL){free(m_p);m_p = NULL;m_len = 0;}}
protected:
private:char *m_p ;int m_len; 
};//對象析構的時候 出現coredump
void objplaymain()
{Name obj1("abcdefg");Name obj2 = obj1;  //C++編譯器提供的 默認的copy構造函數  淺拷貝Name obj3("obj3");obj3 = obj1;  // C++編譯器提供的 等號操作 也屬 淺拷貝//obj3.operator=(obj1)//operato=(Name &obj1)obj1 = obj2 = obj3;//obj2.operator=(obj3);//obj1 = void;
}void main()
{objplaymain();cout<<"hello..."<<endl;system("pause");return ;
}

3.重載下標運算符

  • [ ]運算符用于訪問數據對象的元素
  • 重載格式 類型 類 :: operator[] ( 類型 ) ;
  • 只能用成員函數重載,不能用友元函數重載

示例:
設 x 是類 X 的一個對象,則表達式
x [ y ]
可被解釋為
x . operator [ ] ( y )
這里寫圖片描述
這里寫圖片描述

函數返回值當左值需要返回一個引用!

4.帶下標和相等操作符的數組類

  • 類的頭文件
#ifndef NEWARRAY_H
#define NEWARRAY_H
#include <iostream>
#include <stdlib.h>class NewArray
{
public:NewArray();NewArray(int _len);NewArray(const NewArray & obj);~NewArray();void setData(int index,int var);int getData(int index);int length();int& operator[](int i);NewArray& operator=(NewArray& obj);bool operator==(NewArray& obj);bool operator!=(NewArray& obj);private:int m_len;int *m_buf;
};#endif // NEWARRAY_H
  • 類的實現文件
#include "newarray.h"NewArray::NewArray()
{m_buf = NULL;m_len = -1;
}NewArray::NewArray(int _len)
{if(_len < 0)_len = 0;m_len = _len;m_buf = new int[m_len];}
NewArray::NewArray(const NewArray & obj)
{m_len = obj.m_len;m_buf = new int[m_len];for(int i = 0;i < m_len;i++){m_buf[i] = obj.m_buf[i];}
}
NewArray::~NewArray()
{if(m_buf != NULL){delete []m_buf;m_buf = NULL;m_len = -1;}
}void NewArray::setData(int index,int var)
{m_buf[index] = var;
}
int NewArray::getData(int index)
{return  m_buf[index];
}
int NewArray::length()
{return m_len;
}int& NewArray::operator[](int i)
{return m_buf[i];
}
NewArray& NewArray::operator=(NewArray& obj)
{if(m_buf != NULL){delete []m_buf;m_len = -1;m_buf = NULL;}m_len = obj.m_len;m_buf = new int[m_len];for(int i = 0;i < m_len;i++){m_buf[i] = obj.m_buf[i];}return *this;}
bool NewArray::operator==(NewArray& obj)
{if(m_len != obj.m_len){return false;}for(int i = 0;i < m_len;i++){if(m_buf[i] != obj.m_buf[i]){return false;}}return true;
}
bool NewArray::operator!=(NewArray& obj)
{return !((*this) == obj);
}
  • 測試文件
#include "newarray.h"
using namespace std;int main()
{NewArray  a1(10);for (int i=0; i<a1.length(); i++){//成員函數方式賦值a1.setData(i, i);//下標運算符重載賦值a1[i] = i;//函數返回值當左值,需要返回一個引用//a1.operator [i]}cout<<"\na1: ";for (int i=0; i<a1.length(); i++){//cout<<a1.getData(i)<<" ";//成員函數方式獲取元素//下標運算符方式獲取數組元素cout<<a1[i]<<"\t";}cout<<endl;//賦值運算符重載NewArray a2 = a1;cout<<"\na2: ";for (int i=0; i<a2.length(); i++){cout<<a2.getData(i)<<" ";}cout<<endl;//3NewArray a3(5);{a3 = a1;a3 = a2 = a1;cout<<"\na3: ";for (int i=0; i<a3.length(); i++){cout<<a3[i]<<" ";}}//功能4if (a3 == a1){printf("\nequal\n");}else{printf("\nnot equal\n");}//a3.operator==(a1);//bool operator==(Array &a1);if (a3 != a1){printf("\nnot equal\n");}else{printf("\nequal\n");}////a3.operator!=(a1)// bool operator!=(Array &a1);cout<<"hello..."<<endl;return 1;
}

5.重載函數調用運算符

  • () 運算符用于函數調用
  • 重載格式
類型 類 :: operator() ( 表達式表 ) ;
  • 只能用成員函數重載,不能用友元函數重載

例1
設 x 是類 X 的一個對象,則表達式
x ( arg1, arg2, … )
可被解釋為
x . operator () (arg1, arg2, … )
案例:

  • 例2:用重載()運算符實現數學函數的抽象
#include <iostream>
class  F{ public :  double  operator ( )  ( double x ,  double  y ) ;} ;
double  F :: operator ( )  ( double  x ,  double  y ){ return   x * x + y * y ; }
void main ( )           
{ 
F  f  ;
f.getA();cout << f ( 5.2 , 2.5 ) << endl ;  // f . operator() (5.2, 2.5)
}
  • 例3 用重載()運算符實現 pk 成員函數
#include <iostream.h>
class  F{ public :  double  memFun ( double x ,  double  y ) ;} ;
double  F :: memFun ( double  x ,  double  y ){ return   x * x + y * y ; }
void main ( )           
{ 
F  f  ;cout << f.memFun ( 5.2 , 2.5 ) << endl ;
}

6.不建議重載的運算符

理論知識:
1)&&和||是C++中非常特殊的操作符
2)&&和||內置實現了短路規則
3)操作符重載是靠函數重載來完成的
4)操作數作為函數參數傳遞
5)C++的函數參數都會被求值,無法實現短路規則

#include <cstdlib>
#include <iostream>using namespace std;class Test
{int i;
public:Test(int i){this->i = i;}Test operator+ (const Test& obj){Test ret(0);cout<<"執行+號重載函數"<<endl;ret.i = i + obj.i;return ret;}bool operator&& (const Test& obj){cout<<"執行&&重載函數"<<endl;return i && obj.i;}
};// && 從左向右
void main()
{int a1 = 0;int a2 = 1;cout<<"注意:&&操作符的結合順序是從左向右"<<endl;if( a1 && (a1 + a2) ){cout<<"有一個是假,則不在執行下一個表達式的計算"<<endl;}Test t1 = 0;Test t2 = 1;//if( t1 && (t1 + t2)  )//t1  && t1.operator+(t2)// t1.operator&&(  t1.operator+(t2) )   //1 && || 重載他們 不會產生短路效果if(  (t1 + t2) && t1){//t1.operator+(t2) && t1;//(t1.operator+(t2)).operator&&(t1);cout<<"兩個函數都被執行了,而且是先執行了+"<<endl;}//2 && 運算符的結合性// 兩個邏輯與運算符  在一塊的時候, 采去談 運算符的結合性// 從左到右    (t1 + t2) && t1 ; 運算結果 && t2)//if(  (t1 + t2) && t1 && t2){//t1.operator+(t2) && t1;//(t1.operator+(t2)).operator&&(t1);cout<<"兩個函數都被執行了,而且是先執行了+"<<endl;}system("pause");return ;
}

5.字符串類的實現

  • 頭文件
#ifndef MYSTRING_H
#define MYSTRING_H
#include <iostream>
using namespace std;
#include <stdlib.h>
#include <string.h>
class MyString
{
public:MyString();MyString(int _len);MyString(const char *_str);MyString(const MyString & obj);~MyString();MyString& operator =(const MyString & obj);MyString& operator =(const char * _str);bool operator ==(const MyString & obj);bool operator ==(const char * _str);bool operator !=(const MyString & obj);bool operator !=(const char * _str);bool operator >(const MyString & obj);bool operator >(const char * _str);bool operator <(const MyString & obj);bool operator <(const char * _str);char& operator [](int index);friend ostream& operator<<(ostream & out,MyString & obj);friend istream& operator>>(istream & in,MyString & obj);private:int m_len;char *m_str;
};#endif // MYSTRING_H
  • 實現文件
#include "mystring.h"MyString::MyString()
{m_len = 0;m_str = NULL;
}
MyString::MyString(int _len)
{if(_len < 0)_len = 0;m_len = _len;m_str = new char[m_len+1];memset(m_str,0,m_len);
}MyString::MyString(const char *_str)
{if(_str == NULL){m_len = 0;m_str = new char[m_len+1];strcpy(m_str,"");}else{m_len = strlen(_str);m_str = new char[m_len+1];strcpy(m_str,_str);}}
MyString::MyString(const MyString & obj)
{m_len = obj.m_len;m_str = new char[m_len+1];strcpy(m_str,obj.m_str);
}
MyString::~MyString()
{if(m_str != NULL){delete []m_str;m_str = NULL;m_len = 0;}
}MyString& MyString::operator =(const MyString & obj)
{if(m_str != NULL){delete []m_str;m_str = NULL;m_len = 0;}m_len = obj.m_len;m_str = new char[m_len+1];strcpy(m_str,obj.m_str);return *this;
}MyString& MyString::operator =(const char * _str)
{if(m_str != NULL){delete []m_str;m_str = NULL;m_len = 0;}if(_str == NULL){m_len = 0;m_str = new char[m_len+1];strcpy(m_str,"");}else{m_len = strlen(_str);m_str = new char[m_len+1];strcpy(m_str,_str);}return *this;
}bool MyString::operator ==(const MyString & obj)
{if(m_len != obj.m_len){return false;}return !strcmp(m_str,obj.m_str);}bool MyString::operator ==(const char * _str)
{if(_str == NULL){if(m_len == 0){return true;}else{return false;}}else{if(m_len == strlen(_str)){return !strcmp(m_str,_str);}else{return false;}}}bool MyString::operator !=(const MyString & obj)
{return !((*this) == obj);
}bool MyString::operator !=(const char * _str)
{return !((*this) == _str);
}bool MyString::operator >(const MyString & obj)
{if(strcmp(m_str,obj.m_str) > 0){return true;}else{return false;}
}bool MyString::operator >(const char * _str)
{if(strcmp(m_str,_str) > 0){return true;}else{return false;}
}bool MyString::operator <(const MyString & obj)
{if(strcmp(m_str,obj.m_str) < 0){return true;}else{return false;}
}bool MyString::operator <(const char * _str)
{if(strcmp(m_str,_str) < 0){return true;}else{return false;}
}char& MyString::operator [](int index)
{return m_str[index];
}ostream& operator<<(ostream & out,MyString & obj)
{out<<obj.m_str;return out;
}istream& operator>>(istream & in,MyString & obj)
{in>>obj.m_str;return in;
}
  • 測試文件
#define _CRT_SECURE_NO_WARNINGS#include "mystring.h"void main01()
{MyString s1;MyString s2("s2");MyString s2_2 = NULL;MyString s3 = s2;MyString s4 = "s4444444444";//測試運算符重載 和 重載[]//=s4 = s2;s4 = "s2222";s4[1] = '4';printf("%c", s4[1]);cout<<s4 <<endl;//ostream& operator<<(ostream &out, MyString &s)//char& operator[] (int index)//MyString& operator=(const char *p);//MyString& operator=(const MyString &s);cout<<"hello..."<<endl;system("pause");return ;
}void main02()
{MyString s1;MyString s2("s2");MyString s3 = s2;if (s2 == "aa"){printf("相等");}else{printf("不相等");}if (s3 == s2){printf("相等");}else{printf("不相等");}}
void main03()
{MyString s1;MyString s2("s2");MyString s3 = s2;s3 = "aaa";if (s3 < "bbbb" ){printf("s3 小于 bbbb");}else{printf("s3 大于 bbbb");}MyString s4 = "aaaaffff";//strcpy(s4.c_str(), "aa111"); //MFCcout<<s4<<endl;
}void main011()
{MyString s1(128);cout<<"\n請輸入字符串(回車結束)";cin>>s1;cout<<s1;system("pause");}int main()
{MyString s1(128);cout<<"\n請輸入字符串(回車結束)";cin>>s1;cout<<s1<<endl;system("pause");return 0;}

總結

  • 操作符重載是C++的強大特性之一
  • 操作符重載的本質是通過函數擴展操作符的語義
  • operator關鍵字是操作符重載的關鍵
  • friend關鍵字可以對函數或類開發訪問權限
  • 操作符重載遵循函數重載的規則
  • 操作符重載可以直接使用類的成員函數實現
  • =, [], ()和->操作符只能通過成員函數進行重載
  • ++操作符通過一個int參數進行前置與后置的重載
  • C++中不要重載&&和||操作符

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/448372.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/448372.shtml
英文地址,請注明出處:http://en.pswp.cn/news/448372.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Cookie / Session 的機制與安全

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Cookie和Session是為了在無狀態的HTTP協議之上維護會話狀態&#xff0c;使得服務器可以知道當前是和哪個客戶在打交道。本文來詳細討論C…

手動擋

定義 手動擋&#xff0c;即用手撥動變速桿才能改變變速器內的齒輪嚙合置&#xff0c;改變傳動比&#xff0c;從而達到變速的目的。作用 一方面提供了手動的樂趣 另外一方面就是通過手動自主控制轉速&#xff0c;還可以遲延或提前換檔。駕駛技巧 市區內應直視前方五…

Servlet快速入門及運行流程

一、Servlet快速入門 1.創建一個web工程 2.在JavaResource中src下創建一個包名稱為com.myxq.servlet 3.在創建的servlet包當中創建一個class文件起名為FirstServlet 4.進入該class實現一個Servlet接口&#xff0c;實現它未實現的方法 重點看service方法在該方法當中寫入一句話進…

C++之多繼承

1.基礎知識 1.1 類之間的關系 has-A&#xff0c;uses-A 和 is-A has-A 包含關系&#xff0c;用以描述一個類由多個“部件類”構成。實現has-A關系用類成員表示&#xff0c;即一個類中的數據成員是另一種已經定義的類。 常和構造函數初始化列表一起使用 uses-A 一個類部分地…

自動擋

定義 所謂自動擋&#xff0c;就是不用駕駛者去手動換檔&#xff0c;車輛會根據行駛的速度和交通情況自動選擇合適的檔位行駛。作用 能根據路面狀況自動變速&#xff0c;使駕駛者可以全神貫地注視路面交通而不會被換檔搞得手忙腳亂。工作原理 自動變速器&#xff0c…

聊一聊 cookie

我們看到的 cookie 前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 我自己創建了一個網站&#xff0c;網址為http://ppsc.sankuai.com。在這個網頁中我設置了幾個cookie&#xff1a;JS…

跨域資源共享 CORS 詳解

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 CORS是一個W3C標準&#xff0c;全稱是"跨域資源共享"&#xff08;Cross-origin resource sharing&#xff09;。 它允許瀏覽…

油門

定義 油門是內燃機上控制燃料供量的裝置。作用 是汽車發動機與摩托車油箱之間的閥門&#xff0c;控制汽油的量。操作注意 1.空車起步勿用大油門&#xff0c;以小油門為宜&#xff0c;負荷起步則以中油門為宜。 2.啟動時將油門放在合適位&#xff0c;使機件不易磨損。…

C++之泛型編程(模板)

1.模板綜述 背景 有時候許多函數或子程序的邏輯結構是一樣的&#xff0c;只是要處理的數據類型不一樣有時候多個類具有相同邏輯的成員函數和成員變量&#xff0c;只是成員變量的數據類型以及成員函數的參數類型不一樣模板就是解決數據類型不一致造成代碼冗余的一種機制&#xf…

Base64轉PDF、PDF轉IMG(使用pdfbox插件)

--添加依賴 <!-- https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox --><dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.12</version></dependency&…

const的用法,特別是用在函數后面

原文出處&#xff1a;http://blog.csdn.net/zcf1002797280/article/details/7816977

圖解 Linux 安裝 JDK1.8 、配置環境變量

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. 到官網下載 JDK 1.8 https://www.oracle.com/technetwork/java/javase/downloads/index.html 2. 用 rz 命令把 jdk-8u191-linux-x6…

剎車

定義 剎車就是可以減慢車速的機械制動裝置&#xff0c;又名減速器。簡單來說&#xff0c;汽車剎車踏板在方向盤下面&#xff0c;踩住剎車踏板&#xff0c;則使剎車杠桿聯動受壓并傳至到剎車鼓上的剎車片卡住剎車輪盤&#xff0c;使汽車減速或停止運行。作用 目的是減速&a…

【原創】Performanced C++ 經驗規則 第五條:再談重載、覆蓋和隱藏

第五條&#xff1a;再談重載、覆蓋和隱藏 在C中&#xff0c;無論在類作用域內還是外&#xff0c;兩個&#xff08;或多個&#xff09;同名的函數&#xff0c;可能且僅可能是以下三種關系&#xff1a;重載&#xff08;Overload&#xff09;、覆蓋&#xff08;Override&#xff0…

C++之純虛函數和抽象類

純虛函數和抽象類 1.基本概念 2.案例 #include <iostream> using namespace std;////面向抽象類編程(面向一套預先定義好的接口編程)//解耦合 ....模塊的劃分class Figure //抽象類 { public://閱讀一個統一的界面(接口),讓子類使用,讓子類必須去實現virtual void get…

解決: -bash: $‘\302\240docker‘: command not found

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 我只是運行 一條很簡單的啟動容器的命令&#xff0c;多次執行都報錯&#xff0c;報錯如題&#xff1a; -bash: $\302\240docker: comma…

換擋/掛檔

定義 換擋/掛檔是指變速器&#xff0c;用于轉變發動機曲軸的轉矩及轉速&#xff0c;以適應汽車在起步、加速、行駛以及克服各種道路阻礙等不同行駛條件下對驅動車輪牽引力及車速不同要求的需要。作用 使汽車能以非常低的穩定車速行駛&#xff0c;而這種低的轉速只靠內然…

sql:無法解決 equal to 操作中 Chinese_PRC_CI_AS 和 Chinese_Taiwan_Stroke_CI_AS 之間的排序規則沖突。...

--無法解決 equal to 操作中 "Chinese_PRC_CI_AS" 和 "Chinese_Taiwan_Stroke_CI_AS" 之間的排序規則沖突。 CREATE VIEW View_VipBranchStaffBranchList AS select VipBranchStaff.*,geovindu_branch.B_Name,VipExamCountry.ExamCountryName from VipBran…

【汽車取證篇】GA-T 1998-2022《汽車車載電子數據提取技術規范》(附下載)

【汽車取證篇】GA-T 1998-2022《汽車車載電子數據提取技術規范》&#xff08;附下載&#xff09; GA-T 1998-2022《汽車車載電子數據提取技術規范》標準—【蘇小沐】 總結 公眾號回復關鍵詞【汽車取證】自動獲取資源合集&#xff0c;如鏈接失效請留言&#xff0c;便于…

解決: Client does not support authentication protocol requested by server; consider upgrading MySQL

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1. 在服務器上把 mysql 裝好后&#xff0c;運行起來。 2. navicat 死活連接不上&#xff0c;在網上查說是要改數據庫賬號、密碼什么的&…