C++(友元和運算符重載)

目錄

友元:

友元函數:

示例:

友元類:

示例:

優點:

注意事項:

運算符重載:

注意:

示例:


友元:

C++中如果想要外部函數或者類對一個類的private(私有成員)和protected(保護成員),可以通過使用friend關鍵字對其進行聲明。

聲明位置靈活,可以在類內任何訪問區域進行友元聲明。

友元函數:

友元函數一般在運算符重載和需要訪問私有數據的全局函數進行使用。友元函數是聲明在類內的非成員函數,可以訪問該類的所有成員(包括私有和保護成員)。

示例:

通過友元函數訪問Student類的私有成員_name,在類內聲明GetStudentName()友元函數,在類外進行定義來。

#include <iostream>
#include <string>
#include <thread>class Student {friend void GetStudentName(const Student& student);
public:Student():_name(""),_age(0),_data(new int(0)) {std::cout << "無參構造" << std::endl;}Student(std::string name, int age,int number):_name(name),_age(age),_data(new int(number)) {std::cout << "有參構造" << std::endl;}Student(const Student &student):_name(student._name),_age(student._age) {//const可以加可以不加,主要是為了防止對參數進行修改,但是&是必須加std::cout << "拷貝構造" << std::endl;_data = new int();*_data = *student._data;}Student(Student && student):_name(std::move(student._name)),_age(student._age),_thread(std::move(student._thread)){std::cout << "移動構造" << std::endl;_data = new int();*_data = std::move(*(student._data));}~Student() {std::cout << "析構函數" << std::endl;delete _data;}void GetTarget() {std::cout << "獲取的target的值:";std::cout << _target << std::endl;std::cout << std::endl;}void ModifyTarget(int target) {std::cout << "修改target之后的值:";_target = target;std::cout << _target<<std::endl;}void GetName() {std::cout << _name << std::endl;}void GetAge() {std::cout << _age << std::endl;}void GetData() {std::cout << _data << std::endl;}
private:std::string _name;int _age;static int _target;//類內聲明,類外初始化std::thread _thread;int* _data;
};
int Student::_target = 100;void GetStudentName(const Student& student) {std::cout << student._name << std::endl;
}int main() {Student student1("小明",16,10);GetStudentName(student1);return 0;
}

運行結果:

友元類:

友元類是其所有成員均可以訪問另一個類的私有成員和保護成員的類。需要注意的是:

類A聲明為類B為友元,不意味著類B自動授予類A的訪問權限,類B可以訪問類A的私有成員和保護成員,但是類A不是類B的友元,所以不能訪問類B的私有成員和保護成員。

如果類B是類A的友元類,同時類C是類B的友元,類C是不會自動成為類A的友元,也就是不會有傳遞性。

基類的派生類不會繼承基類的友元關系,也就是沒有繼承性。

示例:

創建一個獲取Student類的私有成員_name的類,在其成員函數中定義獲取的成員函數func()。

#include <iostream>
#include <string>
#include <thread>class Student {friend void GetStudentName(const Student& student);
public:Student():_name(""),_age(0),_data(new int(0)) {std::cout << "無參構造" << std::endl;}Student(std::string name, int age,int number):_name(name),_age(age),_data(new int(number)) {std::cout << "有參構造" << std::endl;}Student(const Student &student):_name(student._name),_age(student._age) {//const可以加可以不加,主要是為了防止對參數進行修改,但是&是必須加std::cout << "拷貝構造" << std::endl;_data = new int();*_data = *student._data;}Student(Student && student):_name(std::move(student._name)),_age(student._age),_thread(std::move(student._thread)){std::cout << "移動構造" << std::endl;_data = new int();_data = std::move(student._data);}~Student() {std::cout << "析構函數" << std::endl;delete _data;}void GetTarget() {std::cout << "獲取的target的值:";std::cout << _target << std::endl;std::cout << std::endl;}void ModifyTarget(int target) {std::cout << "修改target之后的值:";_target = target;std::cout << _target<<std::endl;}Student operator+(const Student& other)const {Student temp;temp._age=this->_age + other._age;temp._data = new int(*this->_data + *other._data);return temp;}Student& operator=(const Student& other) {if (this == &other) {return *this;}delete _data;this->_name = other._name;this->_age = other._age;this->_data = new int();*this->_data = *other._data;std::cout << "拷貝賦值運算符" << std::endl;return *this;}Student& operator=(Student&& other)noexcept {if (this == &other) {return *this;}delete this->_data;this->_name = std::move(other._name);this->_age = other._age;this->_data = other._data;other._data = nullptr;std::cout << "移動賦值運算符" << std::endl;return *this;}Student& operator++() {this->_age++;(*this->_data)++;return *this;}const Student operator++(int) {Student temp(*this);this->_age++;(*this->_data)++;return temp;}friend std::ostream& operator<<(std::ostream& os, Student& other);
private:std::string _name;int _age;static int _target;//類內聲明,類外初始化std::thread _thread;int* _data;
};
int Student::_target = 100;void GetStudentName(const Student& student) {std::cout << student._name << std::endl;
}std::ostream& operator<<(std::ostream& os, Student& other) {os << other._name << "  "<< other._age << "  "<< *other._data << std::endl;return os;
}int main() {std::cout << "構造student1和student2:" << std::endl;Student student1("小明",16,10);Student student2("小剛", 10, 10);std::cout << student2;std::cout << student1;std::cout << std::endl << "構造student3:" << std::endl;Student student3;student3=student1 + student2;std::cout << student3;std::cout <<std::endl<< "對student1進行前置++,對student2進行后置++:" << std::endl;Student student5=++student1;Student student6=student2++;std::cout << "前置++:" << std::endl;std::cout << student1;std::cout << student5;std::cout << "后置++:" << std::endl;std::cout << student2;std::cout << student6;std::cout << "移動賦值運算符:" << std::endl;Student student7;student7=std::move(student2);std::cout << student7;return 0;
}

運行結果:

優點:

避免了共有接口簡介訪問私有數據,支持特殊的場景,比如運算符重載等。

注意事項:

友元會破壞類的封裝性,不能夠通過繼承或者嵌套自動傳遞,會導致代碼的耦合度增加,維護難度上升。

優先使用成員函數或者公有接口,在必要時使用友元,盡量使用友元函數不使用友元類,減少權限的開放。

運算符重載:

通過成員函數或者友元函數重新定義運算符對自定義類型的操作行為。

注意:

運算符重載不能夠創建新的運算符。

不能夠改變運算符的優先級和結合性。

并非所有的運算符都能夠進行重載,比如成員當問運算符、成員指針運算符、作用域解析運算符、條件運算符、sizeof和typeid運算符不能夠進行重載。

示例:

對"+"、"<<"、"="、"前置++"、"后置++"進行重載。"-"、"*"、和"/"和"+"是一樣的思路。注意區分前置++和后置++的區別,還需要注意重載時,前置++和后置++的函數參數區別。移動語義操作中一定注意將被移動對象的指針置空,防止出現雙重釋放或者懸空指針問題。

#include <iostream>
#include <string>
#include <thread>class Student {friend void GetStudentName(const Student& student);
public:Student():_name(""),_age(0),_data(new int(0)) {std::cout << "無參構造" << std::endl;}Student(std::string name, int age,int number):_name(name),_age(age),_data(new int(number)) {std::cout << "有參構造" << std::endl;}Student(const Student &student):_name(student._name),_age(student._age) {//const可以加可以不加,主要是為了防止對參數進行修改,但是&是必須加std::cout << "拷貝構造" << std::endl;_data = new int();*_data = *student._data;}Student(Student && student):_name(std::move(student._name)),_age(student._age),_thread(std::move(student._thread)){std::cout << "移動構造" << std::endl;_data = new int();_data = std::move(student._data);}~Student() {std::cout << "析構函數" << std::endl;delete _data;}void GetTarget() {std::cout << "獲取的target的值:";std::cout << _target << std::endl;std::cout << std::endl;}void ModifyTarget(int target) {std::cout << "修改target之后的值:";_target = target;std::cout << _target<<std::endl;}Student operator+(const Student& other)const {Student temp;temp._age=this->_age + other._age;temp._data = new int(*this->_data + *other._data);return temp;}Student& operator=(const Student& other) {if (this == &other) {return *this;}delete _data;this->_name = other._name;this->_age = other._age;this->_data = new int();*this->_data = *other._data;std::cout << "拷貝賦值運算符" << std::endl;return *this;}Student& operator=(Student&& other)noexcept {if (this == &other) {return *this;}delete this->_data;this->_name = std::move(other._name);this->_age = other._age;this->_data = other._data;other._data = nullptr;std::cout << "移動賦值運算符" << std::endl;return *this;}Student& operator++() {this->_age++;(*this->_data)++;return *this;}const Student operator++(int) {Student temp(*this);this->_age++;(*this->_data)++;return temp;}friend std::ostream& operator<<(std::ostream& os, Student& other);
private:std::string _name;int _age;static int _target;//類內聲明,類外初始化std::thread _thread;int* _data;
};
int Student::_target = 100;void GetStudentName(const Student& student) {std::cout << student._name << std::endl;
}std::ostream& operator<<(std::ostream& os, Student& other) {os << other._name << "  "<< other._age << "  "<< *other._data << std::endl;return os;
}int main() {std::cout << "構造student1和student2:" << std::endl;Student student1("小明",16,10);Student student2("小剛", 10, 10);std::cout << student2;std::cout << student1;std::cout << std::endl << "構造student3:" << std::endl;Student student3;student3=student1 + student2;std::cout << student3;std::cout <<std::endl<< "對student1進行前置++,對student2進行后置++:" << std::endl;Student student5=++student1;Student student6=student2++;std::cout << "前置++:" << std::endl;std::cout << student1;std::cout << student5;std::cout << "后置++:" << std::endl;std::cout << student2;std::cout << student6;std::cout << "移動賦值運算符:" << std::endl;Student student7;student7=std::move(student2);std::cout << student7;return 0;
}

運行結果:

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

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

相關文章

和平精英風格射擊游戲開發指南

本教程將完整講解如何開發一款和平精英風格的HTML射擊游戲&#xff0c;涵蓋核心設計理念、代碼架構與關鍵實現細節。 核心設計架構 游戲機制系統 角色控制系統&#xff1a;通過鍵盤實現玩家移動戰斗系統&#xff1a;子彈發射與碰撞檢測道具系統&#xff1a;武器、彈藥和醫療包收…

21.1 《24GB顯存搞定LLaMA2-7B指令微調:QLoRA+Flash Attention2.0全流程實戰》

24GB顯存搞定LLaMA2-7B指令微調:QLoRA+Flash Attention2.0全流程實戰 實戰 LLaMA2-7B 指令微調 一、指令微調技術背景 指令微調(Instruction Tuning)是大模型訓練中的關鍵技術突破點。與傳統全量微調(Full Fine-Tuning)相比,指令微調通過特定格式的指令-響應數據訓練,…

周志華《機器學習導論》第10章 降維與度量學習

https://www.lamda.nju.edu.cn/aml24fall/slides/Chap10.pptx 目錄 1.MDS (Multiple Dimensional Scaling) 多維縮放方法 2. 主成分分析 (Principal Component Analysis, PCA) 2.1 凸優化證明 2.2 人臉識別降維應用 3. 核化PCA 4. 流行學習 4.1 LLE 局部線性嵌入&#…

Kubernetes 彈性伸縮:深入講解 HPA 和 VPA

1. 介紹 Kubernetes 提供了多種資源管理方式&#xff0c;其中 彈性伸縮&#xff08;Auto-scaling&#xff09;是最重要的特性之一。彈性伸縮可以根據應用的負載變化自動調整 Pod 的數量和資源&#xff0c;以確保在高負載下應用能夠正常運行&#xff0c;而在低負載時節省資源。在…

大數據畢業設計選題推薦-基于大數據的家庭能源消耗數據分析與可視化系統-Hadoop-Spark-數據可視化-BigData

?作者主頁&#xff1a;IT畢設夢工廠? 個人簡介&#xff1a;曾從事計算機專業培訓教學&#xff0c;擅長Java、Python、PHP、.NET、Node.js、GO、微信小程序、安卓Android等項目實戰。接項目定制開發、代碼講解、答辯教學、文檔編寫、降重等。 ?文末獲取源碼? 精彩專欄推薦?…

【Spring】原理解析:Spring Boot 自動配置的核心機制與實戰剖析

一、引言在當今的 Java 開發領域&#xff0c;Spring Boot 憑借其快速搭建項目、簡化配置等優勢&#xff0c;成為了眾多開發者的首選框架。而 Spring Boot 自動配置作為其核心特性之一&#xff0c;極大地提升了開發效率&#xff0c;讓開發者能夠更專注于業務邏輯的實現。本文將深…

Java forEach中不能用i++的原因以及代替方案

因為在 Lambda 表達式內部訪問的外部局部變量必須是 final 或 effectively final&#xff08;事實最終變量&#xff09;&#xff0c;而 i 操作試圖改變這個變量的值&#xff0c;違反了這一規定。下面我們來詳細拆解這個問題&#xff0c;讓你徹底明白。1. 一個具體的例子我們先看…

第十四屆藍橋杯青少組C++選拔賽[2023.1.15]第二部分編程題(2 、尋寶石)

參考程序&#xff1a;#include <bits/stdc.h> using namespace std;int main() {int N;cin >> N; // 讀入盒子數vector<int> a(N);for (int i 0; i < N; i) cin >> a[i]; // 讀入每個盒子的寶石數// N > 3&#xff08;題目保證&#x…

9120 部 TMDb 高分電影數據集 | 7 列全維度指標 (評分 / 熱度 / 劇情)+API 權威源 | 電影趨勢分析 / 推薦系統 / NLP 建模用

一、引言在影視行業分析與數據科學實踐中&#xff0c;高分電影數據的深度挖掘已成為平臺優化內容推薦、制片方研判市場趨勢、影迷發現優質作品的核心支撐 —— 通過上映年份與評分的關聯可捕捉電影質量演變、依托熱度與投票數能定位爆款潛質、結合劇情概述可開展情感與主題分析…

Tomcat PUT方法任意寫文件漏洞學習

1 PUT請求 PUT請求是一種在HTTP協議中常見的請求方法 1.1 基本原理 PUT請求是一種用于向指定資源位置上傳新的實體數據的請求方法&#xff0c;與其他請求方法的區別在于&#xff0c;PUT請求用于創建或者更新只當資源位置的實體數據。它與GET請求不同&#xff0c;PUT請求會替換掉…

【C++基礎】初識模板——一起步入泛型編程的大門

引言在 C 世界里&#xff0c;模板&#xff08;Template&#xff09;就像一把萬能鑰匙。它允許你編寫通用的代碼&#xff0c;讓編譯器在需要的時候為具體類型生成對應的函數或類。換句話說&#xff0c;模板是 C 泛型編程&#xff08;Generic Programming&#xff09; 的基石。 如…

項目管理框架如何影響團隊協作

在項目執行過程中&#xff0c;項目管理框架不僅是一套工具和流程&#xff0c;更是團隊協作方式的基礎。不同的項目管理框架會深刻影響團隊溝通效率、任務分配、決策方式和整體協同效果。 傳統框架通常強調層級與計劃&#xff0c;帶來高度規范化的協作&#xff1b;敏捷框架則強調…

正向代理,反向代理,負載均衡還有nginx

這是一個非常核心且重要的后端/運維知識領域。我會用盡可能清晰易懂的方式&#xff0c;結合生動的比喻&#xff0c;為你詳細梳理這些概念。核心概念一覽我們先從一個宏觀的角度來理解它們之間的關系&#xff1a;代理&#xff08;Proxy&#xff09;&#xff1a; 一個中間人的角色…

WebSocket壓縮傳輸優化:機器視覺高清流在DCS中的低延遲方案

引言在現代工業自動化領域&#xff0c;分布式控制系統&#xff08;DCS&#xff09;正面臨著前所未有的數據挑戰。隨著機器視覺技術的廣泛應用&#xff0c;高清視頻流已成為監控產品質量、檢測設備異常和保障生產安全的重要手段。然而&#xff0c;將720P、1080P甚至4K分辨率的高…

《Linux常見命令》

ls 功能&#xff1a;列出目錄下的子目錄與文件&#xff0c;對于文件&#xff0c;還會列出文件名及其他信息。 語法&#xff1a;ls [選項] [目錄或文件] 1.常用選項及說明選項說明-a列出目錄下的所有文件&#xff0c;包括以 . 開頭的隱含文件-d將目錄象文件一樣顯示&#xff0c;…

Python數據分析:函數定義時的位置參數。

目錄1 代碼示例2 歡迎糾錯3 免費爬蟲4 論文寫作/Python 學習智能體1 代碼示例 直接上代碼。 def pargs1(a, b):"""先看確定數量的位置參數。最簡單的位置參數。a和b都叫而且只能叫“位置參數”。所謂確定數量&#xff0c;很明顯&#xff0c;是兩個就是兩個&…

《沒有架構圖?用 netstat、ss、tcpdump 還原服務連接與數據流向》

&#x1f4e2; 你是否遇到過這些問題&#xff1f; 接手一個老項目&#xff0c;只有服務器賬號&#xff0c;沒有架構圖&#xff1f;服務突然異常&#xff0c;但不知道它依賴哪些外部系統&#xff1f;想畫數據流向圖&#xff0c;卻找不到文檔&#xff1f; 別擔心&#xff01;只要…

Redis列表(List):實現隊列/棧的利器,底層原理與實戰

Redis列表&#xff08;List&#xff09;&#xff1a;實現隊列/棧的利器&#xff0c;底層原理與實戰 1. Redis列表概述 1.1 什么是Redis列表 Redis列表&#xff08;List&#xff09;是一個有序的字符串元素集合&#xff0c;支持在頭部和尾部進行高效的插入和刪除操作。它可以…

OpenCV 圖像雙三次插值

文章目錄 一、簡介 二、實現代碼 三、實現效果 參考資料 一、簡介 在數學中,雙三次插值是三次樣條插值(一種將三次插值應用于數據集的方法)的擴展,用于在二維規則網格上插值數據點。插值曲面(指核形狀,而非圖像)比通過雙線性插值或最近鄰插值獲得的相應曲面更平滑。雙三…

【Java實戰?】Spring Security:為Spring Boot應用筑牢安全防線

目錄 一、Spring Security 概述 1.1 Spring Security 核心功能 1.2 Spring Security 與 Shiro 對比 二、Spring Boot 整合 Spring Security 基礎 2.1 整合依賴導入 2.2 默認安全配置 2.3 自定義用戶認證 2.4 自定義登錄與注銷 三、Spring Security 授權控制 3.1 基于角色的授權…