C++之類和對象:初始化列表,static成員,友元,const成員 ……

目錄

const成員函數:

前置++和后置++重載:

取地址及const取地址操作符重載:

初始化列表:

explicit關鍵字:

static成員:

友元:

友元函數:

友元類:

內部類:

匿名對象:

拷貝對象時的一些編譯器優化:


const成員函數:

const修飾的成員函數是const成員函數,修飾成員函數,實際上修飾的是成員函數隱藏的this指針,表明在該函數中不能對類的任何成員進行修改

1. const對象可以調用非const成員函數嗎?不可以

2. 非const對象可以調用const成員函數嗎?可以

3. const成員函數內可以調用其它的非const成員函數嗎?不可以

4. 非const成員函數內可以調用其它的const成員函數嗎?可以

總結來說:權限只可縮小和平移,不可以放大。const調用非const就是一種權限放大。

前置++和后置++重載:

C++規定:后置++重載時多增加一個int 類型的參數,但是調用函數時該參數不用傳遞,編譯器自動傳遞。

//前置++:
Data& Data::operator++()
{*this += 1;// += 這里是在類中重載過的新 += 。return *this;
}
//后置++:注意后置++是先使用再加1,因此需要返回+1之前的舊值
Data Data::operator++(int)
{Data d(*this);*this += 1;return d;
}

取地址及const取地址操作符重載:

這兩個默認成員函數一般不需要管,編譯器自動生成,只有特殊情況,才需要自己寫,比如:讓別人獲取指定的內容。

class Dat
{ 
public :Date* operator&(){return this ;}const Date* operator&()const{return this ;}
private :int _year ; // 年int _month ; // 月int _day ; // 日
}

初始化列表:

構造函數體內給對象賦值,但是還不能叫做初始化,只有叫賦初值初始化只能初始化一次,而構造函數體內可以多次賦值,所以就引出了初始化列表。

初始化列表以冒號開始,逗號分隔,括號里是初始值或者表達式。每個成員變量定義初始化的地方,初始化列表定義的時候需要值,缺省值就是給它的。

class Data
{
public:Data(int year = 2025, int month = 1, int day = 1): _year(year), _month(month), _day(day){}
private:int _year;int _month;int _day;
};

1.每個成員變量在初始化列表中只能出現一次(初始化只能初始化一次)。

2.類中包含以下成員,必須放在初始化列表位置進行初始化:1.引用成員變量 2.const成員變量 3.自定義類型成員(且該類沒有默認構造函數)

3.盡量使用初始化列表初始化,因為不管你是否使用初始化列表,對于自定義類型成員變量, 一定會先使用初始化列表初始化。

4.成員變量在類中聲明次序就是其在初始化列表中的初始化順序,與其在初始化列表中的先后 次序無關

總結:能用初始化列表就用。

explicit關鍵字:

構造函數不僅可以構造與初始化對象,對于單個參數或者除第一個參數無默認值其余均有默認值 的構造函數,還具有類型轉換的作用。

單參數的構造函數支持隱式類型轉換(隱式類型轉換會產生臨時變量)。

上述可以編譯成功 ,實際就是隱式類型轉換,轉換時編譯器產生一個臨時變量,用臨時變量對d1進行賦值,臨時變量是一個無名對象。

用explicit修飾后就失敗了。禁止了隱式類型轉換。要支持隱式類型轉換需要賦值運算符重載,因為我沒寫,所以編譯器自動生成了一個。

static成員:

聲明為static的類成員稱為類的靜態成員,用static修飾的成員變量,稱之為靜態成員變量;用 static修飾的成員函數,稱之為靜態成員函數。靜態成員變量一定要在類外進行初始化

特性:
1. 靜態成員為所有類對象所共享,不屬于某個具體的對象,存放在靜態區

2. 靜態成員變量必須在類外定義,定義時不添加static關鍵字,類中只是聲明

3. 類靜態成員即可用 類名::靜態成員 或者 對象.靜態成員 來訪問

4. 靜態成員函數沒有隱藏的this指針,不能訪問任何非靜態成員

5. 靜態成員也是類的成員,受public、protected、private 訪問限定符的限制

實現一個類,計算程序中創建了多少個類對象:
?

class A
{
public:A(){++_scount; }A(const A& t) {++_scount; }~A() { --_scount; }static int GetACount() {return _scount; }
private:static int _scount;
};int A::_scount = 0;void TestA()
{cout << A::GetACount() << endl;A a1, a2;A a3(a1);cout << A::GetACount() << endl;
}int main()
{TestA();
}

這個例子很好的說明了,靜態類成員是所有對象共享的,靜態成員函數只可訪問靜態成員變量(因為沒有this指針)。

非靜態成員函數可以調用靜態成員函數,但是反之不行,因為非靜態成員必須是對象定義之后才有實際空間,才可以使用成員函數,不然都只是模型而已。

友元:

友元提供了一種突破封裝的方式,有時提供了便利。但是友元會增加耦合度,破壞了封裝,所以 友元不宜多用。 友元分為:友元函數和友元類

友元函數:

友元函數可以直接訪問類的私有成員,它是定義在類外部的普通函數,不屬于任何類,但需要在 類的內部聲明,聲明時需要加friend關鍵字。

下面看個實例:重載 operator<< 和 >> ,因為重載成成員函數,cout的輸出流對象和隱含的this指針在搶占第一個參數的位置,所以重載函數必須成全局函數,但是又會導致類外無法訪問成員,就需要友元:

class Date
{friend ostream& operator<<(ostream& _cout, const Date& d);friend istream& operator>>(istream& _cin, Date& d);
public:Date(int year = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}
private:int _year;int _month;int _day;
};ostream& operator<<(ostream& _cout, const Date& d)
{_cout << d._year << "-" << d._month << "-" << d._day;return _cout;
}istream& operator>>(istream& _cin, Date& d)
{_cin >> d._year;_cin >> d._month;_cin >> d._day;return _cin;
}int main()
{Date d;cin >> d;cout << d << endl;
}

友元函數可以直接訪問類的私有成員,它是定義在類外部的普通函數,不屬于任何類,但需要在 類的內部聲明,聲明時需要加friend關鍵字。

注意:

1.友元函數可訪問類的私有和保護成員,但不是類的成員函數。

2.友元函數不能用const修飾 。

3.友元函數可以在類定義的任何地方聲明,不受類訪問限定符限制。

4.一個函數可以是多個類的友元函數。

5.友元函數的調用與普通函數的調用原理相同

友元類:

友元類的所有成員函數都可以是另一個類的友元函數,都可以訪問另一個類中的非公有成員。

友元關系是單向的,不具有交換性。

比如下述Time類和Date類,在Time類中聲明Date類為其友元類,那么可以在Date類中直接訪問Time類的私有成員變量,但想在Time類中訪問Date類中私有的成員變量則不行。

友元關系不能傳遞 ,如果C是B的友元,B是A的友元,則不能說明C時A的友元。

class Time
{friend class Date;// 聲明日期類為時間類的友元類,則在日期類中就直接訪問Time類中的私有成員變量
public:Time(int hour = 0, int minute = 0, int second = 0): _hour(hour), _minute(minute), _second(second){}
private:int _hour;int _minute;int _second;
};class Date
{
public:Date(int year = 1900, int month = 1, int day = 1):_year(year), _month(month), _day(day){}void SetTimeOfDate(int hour, int minute, int second){// 直接訪問時間類私有的成員變量_t._hour = hour;_t._minute = minute;_t._second = second;}
private:int _year;int _month;int _day;Time _t;
};

內部類:

概念:如果一個類定義在另一個類的內部,這個內部類就叫做內部類。內部類是一個獨立的類, 它不屬于外部類,更不能通過外部類的對象去訪問內部類的成員。外部類對內部類沒有任何優越 的訪問權限。內部類也受訪問限制符的限制。

注意:內部類就是外部類的友元類,參見友元類的定義,內部類可以通過外部類的對象參數來訪 問外部類中的所有成員。但是外部類不是內部類的友元。(內可以訪問外部,外部不能訪問內部

特性: 1. 內部類可以定義在外部類的public、protected、private都是可以的。

2. 注意內部類可以直接訪問外部類中的static成員,不需要外部類的對象/類名。

3. sizeof(外部類)=外部類,和內部類沒有任何關系。

匿名對象:

匿名對象的生命周期只有一行。

class A
{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}
private:int _a;
};int main()
{A aa1;// 定義普通對象不能 A aa1();因為編譯器分不清是函數聲明,還是對象定義//定義匿名對象,匿名對象的特點就是不用取名字,生命周期只有這一行,接下來就會調用析構函數。A();
}

拷貝對象時的一些編譯器優化:

在傳參和傳返回值的過程中,一般編譯器會做一些優化,減少對象的拷貝,提高效率。這個在一些場景下還 是非常有用的。

1.隱式類型,連續構造+拷貝構造->優化為直接構造

2.一個表達式中,連續構造+拷貝構造->優化為一個構造

3.一個表達式中,連續拷貝構造+拷貝構造->優化一個拷貝構造

4.一個表達式中,連續拷貝構造+賦值重載->無法優化

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

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

相關文章

uni-app 中的條件編譯與跨端兼容

uni-app 為了實現一套代碼編譯到多個平臺&#xff08;包括小程序&#xff0c;App&#xff0c;H5 等&#xff09;&#xff0c;引入了條件編譯機制。 通過條件編譯&#xff0c;我們可以針對不同的平臺編寫特定的代碼&#xff0c;從而實現跨端兼容。 一、條件編譯的作用 平臺差異…

Linux平臺下SSH 協議克隆Github遠程倉庫并配置密鑰

目錄 注意&#xff1a;先提前配置好SSH密鑰&#xff0c;然后再git clone 1. 檢查現有 SSH 密鑰 2. 生成新的 SSH 密鑰 3. 將 SSH 密鑰添加到 ssh-agent 4. 將公鑰添加到 GitHub 5. 測試 SSH 連接 6. 配置 Git 使用 SSH 注意&#xff1a;先提前配置好SSH密鑰&#xff0c;然…

[C++] 大數減/除法

目錄 高精度博客 - 前兩講高精度減法高精度除法高精度系列函數完整版 高精度博客 - 前兩講 講次名稱鏈接高精加法[C] 高精度加法(作用 模板 例題)高精乘法[C] 高精度乘法 高精度減法 void subBIG(int x[], int y[], int z[]){z[0] max(x[0], y[0]);for(int i 1; i < …

視頻添加字幕腳本分享

腳本簡介 這是一個給視頻添加字幕的腳本&#xff0c;可以方便的在指定的位置給視頻添加不同大小、字體、顏色的文本字幕&#xff0c;添加方式可以直接修改腳本中的文本信息&#xff0c;或者可以提前編輯好.srt字幕文件。腳本執行環境&#xff1a;windowsmingwffmpeg。本方法僅…

ubuntu nobel + qt5.15.2 設置qss語法識別正確

問題展示 解決步驟 首選項里面的高亮怎么編輯選擇都沒用。如果已經有generic-highlighter和css.xml&#xff0c;直接修改css.xml文件最直接&#xff01; 在generic-highlighter目錄下找到css.xml文件&#xff0c;位置是&#xff1a;/opt/Qt/Tools/QtCreator/share/qtcreator/…

洛谷P7528 [USACO21OPEN] Portals G

P7528 [USACO21OPEN] Portals G luogu題目傳送門 題目描述 Bessie 位于一個由 N N N 個編號為 1 … N 1\dots N 1…N 的結點以及 2 N 2N 2N 個編號為 1 ? 2 N 1\cdots 2N 1?2N 的傳送門所組成的網絡中。每個傳送門連接兩個不同的結點 u u u 和 v v v&#xff08; u …

C++STL——priority_queue

優先隊列 前言優先隊列仿函數頭文件 前言 本篇主要講解優先隊列及其底層實現。 優先隊列 優先隊列的本質就是個堆&#xff0c;其與queue一樣&#xff0c;都是容器適配器&#xff0c;不過優先隊列是默認為vector實現的。priority_queue的接口優先隊列默認為大根堆。 仿函數 …

助力你的Neovim!輕松管理開發工具的魔法包管理器來了!

在現代編程環境中&#xff0c;Neovim 已經成為許多開發者的編輯器選擇。而針對 Neovim 的各種插件與功能擴展&#xff0c;則是提升開發體驗的重要手段。今天我們要介紹的就是一個強大而便捷的開源項目——mason.nvim&#xff0c;一個旨在簡化和優化 Neovim 使用體驗的便攜式包管…

Java-Lambda 表達式

Lambda 表達式是 Java 8 引入的一項重要特性&#xff0c;它提供了一種簡潔的方式來表示匿名函數。Lambda 表達式主要用于簡化函數式接口的實現&#xff0c;使代碼更加簡潔和易讀。以下是關于 Lambda 表達式的詳細闡述&#xff1a; 1. Lambda 表達式的基本語法 Lambda 表達式的…

05 mysql之DDL

一、SQL的四個分類 我們通常可以將 SQL 分為四類&#xff0c;分別是&#xff1a; DDL&#xff08;數據定義語言&#xff09;、DML&#xff08;數據操作語言&#xff09;、 DCL&#xff08;數據控制語言&#xff09;和 TCL&#xff08;事務控制語言&#xff09;。 DDL 用于創建…

1 2 3 4 5順序插入,形成一個紅黑樹

紅黑樹的特性與優點 紅黑樹是一種自平衡的二叉搜索樹&#xff0c;通過額外的顏色標記和平衡性約束&#xff0c;確保樹的高度始終保持在 O(log n)。其核心特性如下&#xff1a; 每個節點要么是紅色&#xff0c;要么是黑色。根節點和葉子節點&#xff08;NIL節點&#xff09;是…

微服務6大拆分原則

微服務6大拆分原則 微服務拆分是指將一個大型應用程序拆分成獨立服務的過程&#xff0c;在微服務拆分時&#xff0c;需要考慮以下6大微服務拆分原則 一、單一職責原則 微服務單一職責原則&#xff0c;是指每個微服務應該專注于解決一個明確定義的業務領域或功能&#xff0c;…

java: Compilation failed: internal java compiler error 報錯解決方案

java: Compilation failed: internal java compiler error 報錯解決方案 如下圖所示&#xff1a; 在編譯的時候提示 java: Compilation failed: internal java compiler error 原因&#xff1a;內部 java 編譯錯誤,一般是編譯版本不匹配。 問題解決 項目中有以下設置JDK版本…

介紹一下ReentrantLock 跟 Synchronized 區別

ReentrantLock 跟 Synchronized 區別 面試回答&#xff1a; 相同點&#xff1a; synchronized 和 ReentrantLock 都是用來保護資源線程安全的。 都可以保證可見性。 synchronized 和 ReentrantLock 都擁有可重入的特點。 從基本語義和概念上說 synchronized: Java 內建的…

第7次課 棧A

課堂學習 棧&#xff08;stack&#xff09; 是一種遵循先入后出邏輯的線性數據結構。 我們可以將棧類比為桌面上的一摞盤子&#xff0c;如果想取出底部的盤子&#xff0c;則需要先將上面的盤子依次移走。我們將盤子替換為各種類型的元素&#xff08;如整數、字符、對象等&…

ts裝飾器

TypeScript 裝飾器是一種特殊類型的聲明&#xff0c;能夠被附加到類聲明、方法、訪問符、屬性或參數上。它本質上是一個函數&#xff0c;會在運行時被調用&#xff0c;并且被裝飾的聲明信息會作為參數傳遞給裝飾器函數。 裝飾器的分類 類裝飾器 類裝飾器作用于類構造函數&…

【金倉數據庫征文】政府項目數據庫遷移:從MySQL 5.7到KingbaseES的蛻變之路

摘要&#xff1a;本文詳細闡述了政府項目中將 MySQL 5.7 數據庫遷移至 KingbaseES 的全過程&#xff0c;涵蓋遷移前的環境評估、數據梳理和工具準備&#xff0c;遷移實戰中的數據源與目標庫連接配置、遷移任務詳細設定、執行遷移與過程監控&#xff0c;以及遷移后的質量驗證、系…

VB與Excel無縫連接實現指南

一、前期準備 引用Excel對象庫&#xff1a; 在VB開發環境中&#xff0c;點擊"項目"→"引用" 勾選"Microsoft Excel XX.X Object Library"&#xff08;XX.X代表版本號&#xff09; 創建Excel應用程序對象&#xff1a; vb Dim xlApp As Excel.…

【MySQL】數據庫、數據表的基本操作

個人主頁&#xff1a;Guiat 歸屬專欄&#xff1a;MySQL 文章目錄 1. MySQL基礎命令1.1 連接MySQL1.2 基本命令概覽 2. 數據庫操作2.1 創建數據庫2.2 查看數據庫2.3 選擇數據庫2.4 修改數據庫2.5 刪除數據庫2.6 數據庫備份與恢復 3. 表操作基礎3.1 創建表3.2 查看表信息3.3 創建…

cursor sign in 網頁登錄成功,sursor軟件里一直登陸不成功沒有登陸信息

今天在使用cursor登陸無法登陸&#xff0c;點擊sigin in打開網址登陸成功后&#xff0c;軟件里一直無法顯示登陸信息。 點擊sigin in 在網址登陸成功后 解決辦法&#xff1a; 方法1.設置windows默認應用為chrome. 辦法2: 刪除代理 cursor上ctrl, 打開設置&#xff0c;找到…