C++之路:函數重載與運算符重載

目錄

  • 函數重載
  • 運算符重載
    • C++運算符重載范圍對照表
      • 注意事項
    • 運算符重載語法
    • 全局運算符重載
    • 類內運算符重載
      • 下面以一個一元運算符為例,介紹特性1:
      • 下面介紹特性3:(必須類內重載的運算符?)

函數重載

?函數重載是指同一個作用域內,可以聲明幾個功能類似的同名函數,但是這些同名函數的形式參數(指參數的個數、類型或者順序)必須不同
函數重載的要點:

  1. 同一作用域的同名函數。
    也就是說,如果兩個同名的函數不在同一個作用域那就不算重載,具體調用在哪個域就使用哪個函數。
  2. 形式參數,也就是傳入的參數。個數、類型或者順序必須不同,編譯器會自動根據傳入的參數判斷使用的是哪個函數。
    ?下面舉例體會:
#include<iostream>
using namespace std;namespace myspace{void myfunction(int){cout<<"Hello from myspace"<<endl;}void myfunction(double){cout<<"Hello from myspace double"<<endl;}
}void myfunction(float)
{cout<<"Hello from global namespace"<<endl;
}   int main()
{myspace::myfunction(10); //輸出Hello from myspace,匹配到myspace::myfunction(int)myspace::myfunction(3.14); ///輸出Hello from myspace double,匹配到myspace::myfunction(double)myfunction(1.23); //輸出Hello from global namespace,匹配到myfunction(float)return 0;
}

運行后輸出的結果如下:
在這里插入圖片描述
兩個在同一個命名空間的函數myfunction,根據其傳入值的類型來決定實際調用哪個。并且當不同命名空間的myfunction調用時,總是選擇最近的一個(全局)。符合預期的結果。

函數重載的好處顯而易見,可以極大程度地避免冗余的函數命名,例如可以add_int和add_double之類的函數合并為一個同名的add,優化代碼復用與維護?。

運算符重載

?運算符重載最經典的一個例子就是iostream中的cin與cout重載的<<與>>。原本>> or <<只是用來作移位操作的,這里被重載為輸入與輸出的功能。
?運算符重載(Operator Overloading)是面向對象編程中的核心特性,允許對已有運算符賦予新的功能以適應自定義數據類型。其本質是通過定義特定函數,改變運算符在處理類或結構體時的行為邏輯,使得對象操作更貼近內置類型的使用方式。簡單來說就是對已有的運算符進行函數重載,賦予新的功能可以重載的運算符有下面:

C++運算符重載范圍對照表

運算符類型可重載運算符不可重載運算符
算術運算符+ - * / % ++ --
關系運算符== != < > <= >=
邏輯運算符&& || !
位運算符& | ^ ~ << >>
賦值運算符= += -= *= /= %= &= |= ^= <<= >>=
其他運算符[] () -> , new delete new[] delete[]:: .* . ?: sizeof typeid
特殊說明流運算符<< >>必須全局重載成員訪問符.等禁止重載

注意事項

  1. 不能改變運算符優先級和結合性
  2. 至少一個操作數為自定義類型
  3. 保持運算符原有語義

運算符重載語法

?運算符重載有著嚴格的語法規定:

返回類型 operator運算符符號(參數列表) { // 實現運算符邏輯 }

?并且重載之后遵循原運算符的計算順序,例如My_class operator+(My_class c1,My_class c2)調用時應該為My_class num3 = num1 + num2

全局運算符重載

?百分之九十以上的運算符重載都是在類內進行的,即使是在類外的全局運算符重載函數,其輸入參數也必須包含一個類對象
例如 int operator+( int a, int b)這樣是不允許的。因為C++標準明確規定:運算符重載至少有一個參數必須是類類型、枚舉類型或對它們的引用,不能重載基本類型(如int)的運算符?。
改成下面這樣可以編譯通過:(string是一個類)

#include<iostream>
#include<string>
using namespace std;void operator+(string a,  int b)
{cout << "hello" << endl;
}int main()
{string s = "h";int i = 10;s + i; //操作符重載return 0;
}

輸出為:
在這里插入圖片描述
?當然了,全局運算符重載的作用可不是像上面這樣用來搞怪的。前面說到了,運算符重載的輸入參數必須有一個是類類型,枚舉類型或對它們的引用,對于類內運算符重載來說,類內運算符重載默認第一個參數(左參數)是類本身指針(this)因此其可以忽略傳入第一個參數的聲明。
?對于全局運算符重載來說全局運算符重載默認第一個參數(左參數)可以是任意類類型,枚舉類型或對它們的引用,并且需顯式聲明所有操作數參數(也就是說全局重載時,operate不能省略第一個傳入的參數。)流運算符的重載必須是全局運算符重載
?下面給正經示例:


// 全局重載+,混合內置類型和類類型
Vector operator*(const Vector& v, double scalar) {return Vector(v.x * scalar, v.y * scalar);
}
// 調用方式
Vector v1 = v * 2.5;  // 合法

友元函數與流運算


#include <iostream>
using namespace std;class Vector {
private:double x, y;
public:Vector(double x=0, double y=0) : x(x), y(y) {}// 聲明友元全局運算符friend Vector operator+(const Vector& v1, const Vector& v2);friend ostream& operator<<(ostream& os, const Vector& v);
};// 實現友元運算符+
Vector operator+(const Vector& v1, const Vector& v2) {return Vector(v1.x + v2.x, v1.y + v2.y);
}// 實現友元流輸出運算符
ostream& operator<<(ostream& os, const Vector& v) {return os << "(" << v.x << ", " << v.y << ")";
}int main() {Vector a(1, 2), b(3, 4);cout << "a + b = " << a + b << endl;return 0;
}

上面的全局運算符重載定義了兩個友元函數:

  1. + 號的重載。
  2. 流運算符 <<的重載。

定義成友元函數是因為兩個全局運算符重載函數不屬于類的成員函數,但它們都要訪問類的私有成員。因此需要在類內聲明它們為類的友元函數。

類內運算符重載

?類內運算符重載有這么幾個核心特性:

  1. 隱式調用this指針。類內重載的運算符函數默認以this作為左操作數(左操作數也必須是當前對象),因此二元運算符只需顯式聲明一個參數(右操作數)?。例如operator+(this,b) == operator+(b),this被省略。
    理論上一元運算符,如++,--之類的類內重載都不需要顯式聲明形參,但有時候為了區分運算的順序,例如a++和++a,需要傳入偽參數。
  2. operator作為成員函數,可直接訪問類的私有成員,無需友元聲明?。
  3. 必須為類內重載的運算符:=(賦值)、[](下標)、()(函數調用)、->(成員訪問)?。

下面以一個一元運算符為例,介紹特性1:

#include<iostream>
using namespace std;class Counter {
public:int count;Counter(int n=0) : count(n) {}// 前綴++(返回引用,避免拷貝)Counter& operator++() {++count;return *this;}// 后綴++(int參數區分)Counter operator++(int) {Counter temp = *this;++count;return temp;}
};int main()
{Counter c;cout << c.count << endl; // 0cout << ++c.count << endl; // 1cout << c.count++ << endl; // 1cout << c.count << endl; // 2return 0;
}

下面介紹特性3:(必須類內重載的運算符?)

  1. 賦值運算符=?
    用于對象間的深拷貝,需處理自賦值問題。
class MyClass {
public:MyClass& operator=(const MyClass& rhs);
};

正常來說,如果沒有自定義賦值運算符編譯器會默認進行淺拷貝,如下:

class BadClass {int* data;
public:BadClass() : data(new int[100]) {}~BadClass() { delete[] data; }
};
BadClass b1, b2;
b2 = b1;  // 危險:兩個對象指向同一內存

什么是淺拷貝?
在C++中,當類包含動態分配的內存時,直接使用默認的賦值運算符會導致淺拷貝問題,前拷貝對于基本類型(如int、double)直接復制值,類類型成員調用其自身的賦值運算符,指針類型就僅復制地址(不復制指向的內容)

上面的代碼進行淺拷貝后,對于b2.data的更改會同步到b1.data(淺拷貝使得二者地址相同)。更好的辦法是下面這樣:

class BadClass {int* data;
public:// ... 原有構造函數和析構函數 ...// 自定義賦值運算符BadClass& operator=(const BadClass& other) {if (this != &other) {  // 防止自賦值delete[] data;      // 釋放原有內存data = new int[100]; //指向新地址std::copy(other.data, other.data + 100, data);  // 值深拷貝}return *this;}
};
  1. 函數調用運算符()仿函數
    仿函數就是讓類的對象能像函數一樣被調用。語法如下:
返回值類型 operator()(傳入參數)

典型例子:


class Adder {int value;
public:Adder(int v) : value(v) {}int operator()(int x) { return x + value; }
};Adder add5(5);
cout << add5(10);  // 輸出15

對于int operator()(int x) { return x + value; },類內運算符重載函數可以訪問類內的成員變量,因此value無需傳入。
3. 下標運算符[]?
提供類似數組的訪問方式,通常返回引用以支持修改。

class Vector {
public:int& operator[](int index);
};
  1. 成員訪問運算符->?
    常用于智能指針或迭代器實現。
class SmartPtr {
public:T* operator->() { return ptr; }
};

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

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

相關文章

七、SpringCloud 項目遷移至 K8s

七、SpringCloud 項目遷移至 K8s 文章目錄 七、SpringCloud 項目遷移至 K8s1、環境準備1.1 集群規劃1.2 SpringCloud 項目架構及遷移需求分析 2、遷移 Eureka 集群2.1 構建及容器化2.2 部署至 K8s2.3 創建通信Service 3、遷移網關服務3.1 構建及容器化3.2 部署至 K8s3.3 創建Se…

通過具有一致性嵌入的大語言模型實現端到端乳腺癌放射治療計劃制定|文獻速遞-最新論文分享

Title 題目 End-to-end breast cancer radiotherapy planning via LMMs with consistency embedding 通過具有一致性嵌入的大語言模型實現端到端乳腺癌放射治療計劃制定 01 文獻速遞介紹 近年來&#xff0c;受大型語言模型&#xff08;LLM&#xff09;啟發的新一代人工智…

MCP Chart Server服務本地部署案例

一、MCP Chart Server介紹 MCP Chart Server是一個專業的圖表生成服務&#xff0c;支持多種圖表類型&#xff0c;適用于數據可視化和分析。 MCP Chart Server是一種用于生成和呈現圖表的服務器端軟件。它提供了一個簡單而強大的方式&#xff0c;讓開發人員和系統管理員可以輕…

復合型浪涌保護器五大核心技術重構電氣防護體系

開篇&#xff1a;從傳統防護到智能守護的技術跨越 在電氣設備面臨浪涌威脅的防護場景中&#xff0c;浪涌保護器&#xff08;SPD&#xff09;始終扮演著關鍵角色。面對傳統SPD在漏電流、續流等方面的技術局限&#xff0c;行業領先企業通過技術整合開發出復合型SPD&#xff0c;以…

c# 詳細分析Task.sleep和Thread.sleep 的區別、使用場景和應用示例

文章目錄 Task.Delay vs Thread.Sleep 詳細分析與使用場景核心區別詳細分析Thread.SleepTask.Delay 性能考量綜合示例高級用法組合延遲與超時實現指數退避重試 總結建議 Task.Delay vs Thread.Sleep 詳細分析與使用場景 核心區別 Task.Delay 和 Thread.Sleep 都用于在代碼中引…

Vue 3 中的 `h` 函數詳解

h 函數是 Vue 3 中用于創建**虛擬 DOM 節點(VNode)**的核心函數&#xff0c;它是 Vue 渲染系統的基石。下面我將全面解釋它的作用、用法和重要性。 1. h 函數的基本概念 h 是 createVNode 的簡稱&#xff0c;來源于"hyperscript"的縮寫傳統。它的主要作用是&#x…

SoapCore 全面介紹:在 .NET Core 中實現 SOAP 服務的現代解決方案

一、什么是 SoapCore&#xff1f; 在現代微服務和 REST API 成為主流的今天&#xff0c;SOAP&#xff08;Simple Object Access Protocol&#xff09;看似已經被邊緣化&#xff0c;但在許多企業和政務系統中&#xff0c;SOAP 仍然是 重要的通信協議。特別是在金融、保險、醫療…

JDBC工具類和SQL 注入問題

在軟件開發中&#xff0c;數據庫安全與高效訪問一直是關鍵課題。本文將圍繞 SQL 注入問題的原理、解決方案&#xff0c;以及 JDBC 開發中的工具類演進和連接池技術展開探討&#xff0c;結合實際代碼示例&#xff0c;為開發者提供清晰的技術實踐指南。 SQL 注入問題的核心原理與…

2022年SEVC SCI2區,分數階蟻群算法FACA:一種基于分數階長期記憶的合作學習方法,深度解析+性能實測

目錄 1.摘要2.分數階微積分基礎知識3.分數階蟻群算法FACA4.分數階蟻群算法FACA數學證明與分析5.結果展示6.參考文獻7.代碼獲取8.算法輔導應用定制讀者交流 1.摘要 本文提出了一種新穎分數階蟻群算法&#xff08;Fractional-Order Ant Colony Algorithm&#xff0c; FACA&#…

java+vue+SpringBoo數字科技風險報告管理系統(程序+數據庫+報告+部署教程+答辯指導)

源代碼數據庫LW文檔&#xff08;1萬字以上&#xff09;開題報告答辯稿ppt部署教程代碼講解代碼時間修改工具 技術實現 開發語言&#xff1a;后端&#xff1a;Java 前端&#xff1a;vue框架&#xff1a;springboot數據庫&#xff1a;mysql 開發工具 JDK版本&#xff1a;JDK1.…

YOLOv12_ultralytics-8.3.145_2025_5_27部分代碼閱讀筆記-augment.py

augment.py ultralytics\data\augment.py 目錄 augment.py 1.所需的庫和模塊 2.class BaseTransform: 3.class Compose: 4.class BaseMixTransform: 5.class CutMix(BaseMixTransform): 6.class CopyPaste(BaseMixTransform): 7.def v8_transforms(dataset, img…

跨芯片 AI 算子庫 FlagGems 正式加入PyTorch 基金會生態項目體系

2025年北京智源大會 PyTorch Day China 論壇上&#xff0c;PyTorch 基金會執行董事 Matt White 宣布高性能通用 AI 算子庫 FlagGems 項目獲得批準&#xff0c;正式加入 PyTorch 生態項目體系。Pytorch基金會于6月26日在推特上進行了官方宣布。 作為唯一支持多種AI芯片架構的算…

vue + vue-router寫登陸驗證的同步方法和異步方法,及頁面組件的分離和后端代碼

先寫一個用vue cdn寫一個登陸驗證的小示例后端代碼 前端719.html <div id"app"><div id"loginForm">//路由層&#xff0c;登陸頁和后臺主頁<router-link to"/">Login</router-link><router-link to"/home&quo…

.netcore 一個mvc到靜態html實現

一、新建Mvc項目 Program.cs添加攔截 二、添加一個集成測試 將頁面轉為html到wwwroot下面 UnitGenHtml.cs using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.VisualStudio.TestPlatform.TestHost;namespace SaaS.OfficialWeb…

實現Taro小程序+nut-ui左滑刪除效果

Taro小程序開發中&#xff0c;使用nut-ui組件&#xff0c;實現左滑刪除卡片效果&#xff08;自定義刪除按鈕樣式&#xff09; html代碼部分 <nut-swipe class"carBox" v-for"(item, index) in carList" :key"item" :ref"(el) > se…

LLM 系列(五):模型訓練篇

一個面向 Java 開發者的 Sring-Ai 示例工程項目&#xff0c;該項目是一個 Spring AI 快速入門的樣例工程項目&#xff0c;旨在通過一些小的案例展示 Spring AI 框架的核心功能和使用方法。 項目采用模塊化設計&#xff0c;每個模塊都專注于特定的功能領域&#xff0c;便于學習和…

Oracle LogMiner分析日志的三種方法示例

Oracle LogMiner分析日志的三種方法示例 方法一:Online Catalog作為日志挖掘字典自動獲取日志模式手動獲取日志模式方法二:Redo Log作為日志挖掘字典自動獲取日志模式手動獲取日志模式方法三:Flat File作為日志挖掘字典自動獲取日志模式手動獲取日志模式?? Oracle LogMine…

Java 中 List.stream() 的全面使用指南(含完整示例)

標簽&#xff1a;Java8, Stream API, 函數式編程, 集合操作 一、前言 隨著 Java 8 的推出&#xff0c;Stream API 成為了處理集合數據的一種高效方式。List.stream() 是 Java Stream API 的入口方法之一&#xff0c;它允許開發者將集合轉換為流&#xff0c;并通過鏈式調用實現…

香港 8C 站群服務器買來可以做哪些業務?

香港8C站群服務器&#xff08;即提供8個不同C段IP地址的服務器&#xff09;憑借多IP獨立分配、低延遲網絡及免備案優勢&#xff0c;適用于以下關鍵業務場景&#xff1a; 一、SEO優化與搜索引擎運營 SEO站群搭建&#xff1a;為 80-100 個網站分配 8 個不同 C 段 IP &#xff0…

UI前端與數字孿生融合新趨勢:智慧醫療的可視化診斷輔助

hello寶子們...我們是艾斯視覺擅長ui設計、前端開發、數字孿生、大數據、三維建模、三維動畫10年經驗!希望我的分享能幫助到您!如需幫助可以評論關注私信我們一起探討!致敬感謝感恩! 一、引言&#xff1a;數字孿生重塑智慧醫療診斷范式 在醫療數字化轉型的浪潮中&#xff0c;數…