第四講:類和對象(下)

1. 再探構造函數


? 之前我們實現構造函數時,初始化成員變量主要使?函數體內賦值,構造函數初始化還有?種?
式,就是初始化列表,初始化列表的使??式是以?個冒號開始,接著是?個以逗號分隔的數據成
員列表,每個"成員變量"后?跟?個放在括號中的初始值或表達式。
? 每個成員變量在初始化列表中只能出現?次,語法理解上初始化列表可以認為是每個成員變量定義初始化的地?。
? 引?成員變量,const成員變量,沒有默認構造的類類型變量,必須放在初始化列表位置進?初始
化,否則會編譯報錯。
? C++11?持在成員變量聲明的位置給缺省值,這個缺省值主要是給沒有顯?在初始化列表初始化的成員使?的。
? 盡量使?初始化列表初始化,因為那些你不在初始化列表初始化的成員也會?初始化列表,如果這個成員在聲明位置給了缺省值,初始化列表會?這個缺省值初始化。如果你沒有給缺省值,對于沒有顯?在初始化列表初始化的內置類型成員是否初始化取決于編譯器,C++并沒有規定。對于沒有顯?在初始化列表初始化的?定義類型成員會調?這個成員類型的默認構造函數,如果沒有默認構造會編譯錯誤。
? 初始化列表中按照成員變量在類中聲明順序進?初始化,跟成員在初始化列表出現的的先后順序?關。建議聲明順序和初始化列表順序保持?致。
初始化列表總結:
?論是否顯?寫初始化列表,每個構造函數都有初始化列表;
?論是否在初始化列表顯?初始化,每個成員變量都要?初始化列表初始化;

#include<iostream>
using namespace std;class Time
{
public:Time(int hour): _hour(hour){cout << "Time()" << endl;}
private:int _hour;};class Date
{
public:Date(int& x, int year = 1, int month = 1, int day = 1): _year(year), _month(month), _day(day), _t(12), _ref(x), _n(1){// error C2512: “Time”: 沒有合適的默認構造函數可?// error C2530 : “Date::_ref” : 必須初始化引?// error C2789 : “Date::_n” : 必須初始化常量限定類型的對象}void Print() const{cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;Time _t; // 沒有默認構造int& _ref; // 引?const int _n; // const
};int main()
{int i = 0;Date d1(i);d1.Print();return 0;
}

#include<iostream>
using namespace std;class Time
{
public:Time(int hour): _hour(hour){cout << "Time()" << endl;}
private:int _hour;};class Date
{
public:Date(): _month(2){cout << "Date()" << endl;}void Print() const{cout << _year << "-" << _month << "-" << _day << endl;}
private:// 注意這?不是初始化,這?給的是缺省值,這個缺省值是給初始化列表的// 如果初始化列表沒有顯?初始化,默認就會?這個缺省值初始化int _year = 1;int _month = 1;int _day;Time _t = 1;const int _n = 1;int* _ptr = (int*)malloc(12);};int main()
{Date d1;d1.Print();return 0;
}

2. 類型轉換


? C++?持內置類型隱式類型轉換為類類型對象,需要有相關內置類型為參數的構造函數。
? 構造函數前?加explicit就不再?持隱式類型轉換。
? 類類型的對象之間也可以隱式轉換,需要相應的構造函數?持。

#include<iostream>
using namespace std;
class A
{
public:// 構造函數explicit就不再?持隱式類型轉換// explicit A(int a1)A(int a1):_a1(a1){}//explicit A(int a1, int a2)A(int a1, int a2):_a1(a1), _a2(a2){}void Print(){cout << _a1 << " " << _a2 << endl;}int Get() const{return _a1 + _a2;}
private:int _a1 = 1;int _a2 = 2;
};
class B
{
public:B(const A& a):_b(a.Get()){}
private:int _b = 0;
};
int main()
{// 1構造?個A的臨時對象,再?這個臨時對象拷?構造aa3// 編譯器遇到連續構造+拷?構造->優化為直接構造A aa1 = 1;aa1.Print();const A& aa2 = 1;// C++11之后才?持多參數轉化A aa3 = { 2,2 };// aa3隱式類型轉換為b對象// 原理跟上?類似B b = aa3;const B& rb = aa3;return 0;
}

3. static成員


? ?static修飾的成員變量,稱之為靜態成員變量,靜態成員變量?定要在類外進?初始化。
? 靜態成員變量為所有類對象所共享,不屬于某個具體的對象,不存在對象中,存放在靜態區。
? ?static修飾的成員函數,稱之為靜態成員函數,靜態成員函數沒有this指針。
? 靜態成員函數中可以訪問其他的靜態成員,但是不能訪問?靜態的,因為沒有this指針。
? ?靜態的成員函數,可以訪問任意的靜態成員變量和靜態成員函數。
? 突破類域就可以訪問靜態成員,可以通過類名::靜態成員 或者 對象.靜態成員 來訪問靜態成員變量和靜態成員函數。
? 靜態成員也是類的成員,受public、protected、private 訪問限定符的限制。
? 靜態成員變量不能在聲明位置給缺省值初始化,因為缺省值是個構造函數初始化列表的,靜態成員變量不屬于某個對象,不?構造函數初始化列表。

#include<iostream>
using namespace std;
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;
int main()
{cout << A::GetACount() << endl;A a1, a2;A a3(a1);cout << A::GetACount() << endl;cout << a1.GetACount() << endl;// 編譯報錯:error C2248: “A::_scount”: ?法訪問 private 成員(在“A”類中聲明)//cout << A::_scount << endl;return 0;
}

4. 友元


? 友元提供了?種突破類訪問限定符封裝的?式,友元分為:友元函數和友元類,在函數聲明或者類聲明的前?加friend,并且把友元聲明放到?個類的??。
? 外部友元函數可訪問類的私有和保護成員,友元函數僅僅是?種聲明,他不是類的成員函數。
? 友元函數可以在類定義的任何地?聲明,不受類訪問限定符限制。
? ?個函數可以是多個類的友元函數。
? 友元類中的成員函數都可以是另?個類的友元函數,都可以訪問另?個類中的私有和保護成員。
? 友元類的關系是單向的,不具有交換性,?如A類是B類的友元,但是B類不是A類的友元。
? 友元類關系不能傳遞,如果A是B的友元, B是C的友元,但是A不是C的友元。
? 有時提供了便利。但是友元會增加耦合度,破壞了封裝,所以友元不宜多?。

#include<iostream>
using namespace std;
// 前置聲明,都則A的友元函數聲明編譯器不認識B
class B;
class A
{// 友元聲明friend void func(const A & aa, const B & bb);
private:int _a1 = 1;int _a2 = 2;};class B
{// 友元聲明friend void func(const A & aa, const B & bb);
private:int _b1 = 3;int _b2 = 4;
};void func(const A & aa, const B & bb)
{cout << aa._a1 << endl;cout << bb._b1 << endl;
}int main()
{A aa;
B bb;
func(aa, bb);return 0;
}
#include<iostream>
using namespace std;class A
{
// 友元聲明friend class B;
private:int _a1 = 1;int _a2 = 2;};
class B
{
public:void func1(const A& aa){cout << aa._a1 << endl;cout << _b1 << endl;}void func2(const A& aa){cout << aa._a2 << endl;cout << _b2 << endl;}
private:int _b1 = 3;int _b2 = 4;
};
int main()
{A aa;B bb;bb.func1(aa);bb.func1(aa);return 0;
}

5. 內部類


? 如果?個類定義在另?個類的內部,這個內部類就叫做內部類。內部類是?個獨?的類,跟定義在全局相?,他只是受外部類類域限制和訪問限定符限制,所以外部類定義的對象中不包含內部類。
? 內部類默認是外部類的友元類。
? 內部類本質也是?種封裝,當A類跟B類緊密關聯,A類實現出來主要就是給B類使?,那么可以考慮把A類設計為B的內部類,如果放到private/protected位置,那么A類就是B類的專屬內部類,其
他地?都?不了。

#include<iostream>
using namespace std;
class A
{
private:static int _k;int _h = 1;public:class B // B默認就是A的友元{public:void foo(const A & a){cout << _k << endl; //OKcout << a._h << endl; //OK}};};int A::_k = 1;int main()
{cout << sizeof(A) << endl;A::B b;A aa;b.foo(aa);return 0;
}

6. 匿名對象


? ? 類型(實參) 定義出來的對象叫做匿名對象,相?之前我們定義的 類型 對象名(實參) 定義出來的叫有名對象
? 匿名對象?命周期只在當前??,?般臨時定義?個對象當前??下即可,就可以定義匿名對象。

#include <iostream>
using namespace std;
class A
{
public:
A(int a = 0)
:_a(a)
{
cout << "A(int a)" << endl;
}
~A()
{
cout << "~A()" << endl;
}
private:
int _a;
};
class Solution {
public:int Sum_Solution(int n) {//...return n;}
};
int main()
{A aa1;// 不能這么定義對象,因為編譯器?法識別下?是?個函數聲明,還是對象定義//A aa1();// 但是我們可以這么定義匿名對象,匿名對象的特點不?取名字,// 但是他的?命周期只有這??,我們可以看到下??他就會?動調?析構函數A();A(1);A aa2(2);// 匿名對象在這樣場景下就很好?,當然還有?些其他使?場景,這個我們以后遇到了再說Solution().Sum_Solution(10);return 0;
}

7. 對象拷?時的編譯器優化


? 現代編譯器會為了盡可能提?程序的效率,在不影響正確性的情況下會盡可能減少?些傳參和傳返回值的過程中可以省略的拷?。
? 如何優化C++標準并沒有嚴格規定,各個編譯器會根據情況??處理。當前主流的相對新?點的編譯器對于連續?個表達式步驟中的連續拷?會進?合并優化,有些更新更"激進"的編譯器還會進?跨?跨表達式的合并優化。

#include<iostream>
using namespace std;
class A
{
public:A(int a = 0):_a1(a){cout << "A(int a)" << endl;}A(const A& aa):_a1(aa._a1){cout << "A(const A& aa)" << endl;}A& operator=(const A& aa){cout << "A& operator=(const A& aa)" << endl;if (this != &aa){_a1 = aa._a1;}return *this;}~A(){cout << "~A()" << endl;}
private:int _a1 = 1;};
void f1(A aa)
{}A f2()
{A aa;return aa;}int main()
{// 傳值傳參A aa1;f1(aa1);cout << endl;// 隱式類型,連續構造+拷?構造->優化為直接構造f1(1);// ?個表達式中,連續構造+拷?構造->優化為?個構造f1(A(2));cout << endl;cout << "***********************************************" << endl;// 傳值返回// 返回時?個表達式中,連續拷?構造+拷?構造->優化?個拷?構造 (vs2019 debug)// ?些編譯器會優化得更厲害,進?跨?合并優化,直接變為構造。(vs2022 debug)f2();cout << endl;// 返回時?個表達式中,連續拷?構造+拷?構造->優化?個拷?構造 (vs2019 debug)// ?些編譯器會優化得更厲害,進?跨?合并優化,直接變為構造。(vs2022 debug)A aa2 = f2();cout << endl;// ?個表達式中,連續拷?構造+賦值重載->?法優化aa1 = f2();cout << endl;return 0;}

總結:

演講主要是對內核對象的進一步深入了解。再探構造函數,我們增加了初始化列表。類型轉換中,內置類型可直接由影視類型轉換。而自定義類型要重寫重載函數。再來就是對static成員、友元和內部類還有匿名對象的補充。如果覺得博主講的不錯的話,請留下點贊和收藏吧,謝謝!未完待續...

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

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

相關文章

linux 安裝mysql8.0;支持國產麒麟,統信uos系統

一&#xff1a;使用我已經改好的mysql linux mysql8.0解壓可用&#xff0c;點我下載 也在國產麒麟系統&#xff0c;統信uos系統也測試過&#xff0c;可用&#xff1b; 下載后&#xff0c;上傳mysql.tar.gz 然后使用root角色去執行幾個命令即可&#xff1b;數據庫密碼&#xf…

音頻剪輯軟件少之又少好用

我們平時見到的圖片以及視頻編輯工具非常多&#xff0c;但是音頻剪輯軟件卻是少之又少&#xff0c;更不用說有沒有好用的&#xff0c;今天&#xff0c;給大家帶來一款非常專業的音頻剪輯軟件&#xff0c;而且是會員喔。 軟件簡介 一款手機號登錄即可以享受會員的超專業音頻剪…

論文閱讀:CLIP:Learning Transferable Visual Models From Natural Language Supervision

從自然語言監督中學習可遷移的視覺模型 雖然有點data/gpu is all you need的味道&#xff0c;但是整體實驗和談論豐富度上還是很多的&#xff0c;非常長的原文和超級多的實驗討論&#xff0c;隔著屏幕感受到了實驗的工作量之大。 Abstract 最先進的計算機視覺系統被訓練來預測…

第9篇:數據庫中間件的容錯機制與高可用架構設計

9.1 為什么數據庫中間件需要容錯與高可用設計&#xff1f; 隨著系統復雜性增加&#xff0c;數據庫中間件不僅承載 SQL 路由、分片、事務控制等核心職責&#xff0c;也成為系統的 單點風險源。 為確保系統 724 小時穩定運行&#xff0c;中間件必須具備&#xff1a; 自動故障檢測…

c#壓縮與解壓縮-SharpCompress

SharpCompress SharpCompress 是一個開源項目庫&#xff0c;能夠處理文件。c#庫對于壓縮已經有很多&#xff0c;可以隨意選擇&#xff0c;看了SharpCompress感覺比較簡潔&#xff0c;還是介紹給大家。 項目地址&#xff1a; sharpcompress 項目使用 引入nuget包&#xff1…

Go中的協程并發和并發panic處理

1 協程基礎 1.1 協程定義&#xff08;Goroutine&#xff09; 概念&#xff1a;Go 語言特有的輕量級線程&#xff0c;由 Go 運行時&#xff08;runtime&#xff09;管理&#xff0c;相比系統線程&#xff08;Thread&#xff09;&#xff0c;創建和銷毀成本極低&#xff0c;占用…

性能優化筆記

性能優化轉載 https://www.cnblogs.com/tengzijian/p/17858112.html 性能優化的一般策略及方法 簡言之&#xff0c;非必要&#xff0c;不優化。先保證良好的設計&#xff0c;編寫易于理解和修改的整潔代碼。如果現有的代碼很糟糕&#xff0c;先清理重構&#xff0c;然后再考…

frida簡介及環境搭建

frida簡介及環境搭建 一、frida簡介二、frida環境搭建一、frida簡介 frida是一款輕量級的Hook框架,也可以說是一種動態插樁工具,可以插入一些原生代碼到原生app的內存空間去,動態地監視和修改器行為,這些原生平臺可以是Win、Mac、Linux、Android或者iOS。 frida分為兩個部…

Python實例題:Python計算微積分

目錄 Python實例題 題目 代碼實現 實現原理 符號計算&#xff1a; 數值計算&#xff1a; 可視化功能&#xff1a; 關鍵代碼解析 1. 導數計算 2. 積分計算 3. 微分方程求解 4. 函數圖像繪制 使用說明 安裝依賴&#xff1a; 基本用法&#xff1a; 示例輸出&#…

Mybatis 攔截器 與 PageHelper 源碼解析

Mybatis 攔截器 與 PageHelper 源碼解析 一、MyBatis插件機制的設計思想二、Interceptor接口核心解析2.1 核心方法2.2 Intercepts、Signature 注解2.3 自定義攔截器 三、PageHelper 介紹3.1 使用姿勢3.2 參數與返回值3.3 使用小細節 四、PageHelper 核心源碼解析4.1 分頁入口&a…

Linux中 SONAME 的作用

?? 一、從 -lexample 到 SONAME ? 假設你有以下文件結構: /libexample.so → libexample.so.1 /libexample.so.1 → libexample.so.1.0.0 /libexample.so.1.0.0 # SONAME: libexample.so.1/libexample.so.2 → libexample.so.2.0.0 /libexample.so.2.0…

熱門消息中間件匯總

文章目錄 前言RabbitMQ基本介紹核心特性適用場景 Kafka基本介紹核心特性適用場景 RocketMQ基本介紹核心特性適用場景 NATS基本介紹核心特性適用場景 總結選型建議與未來趨勢選型建議未來趨勢 結語 前言 大家后&#xff0c;我是沛哥兒。作為技術領域的老濕機&#xff0c;在消息…

【DAY42】Grad-CAM與Hook函數

內容來自浙大疏錦行python打卡訓練營 浙大疏錦行 知識點: 回調函數lambda函數hook函數的模塊鉤子和張量鉤子Grad-CAM的示例 作業&#xff1a;理解下今天的代碼即可 在深度學習中&#xff0c;我們經常需要查看或修改模型中間層的輸出或梯度。然而&#xff0c;標準的前向傳播和反…

C++032(static變量)

static變量 static變量是靜態存儲變量&#xff0c;定義變量時系統就會為其分配固定的存儲單元&#xff0c;直至整個程序運行結束。之前我們接觸過的全局變量即為static變量&#xff0c;它們存放在靜態存儲區中。使用static關鍵字&#xff0c;可將變量聲明成static變量。例如&a…

N元語言模型 —— 一文講懂!!!

目錄 引言 一. 基本知識 二.參數估計 三.數據平滑 一.加1法 二.減值法/折扣法 ?編輯 1.Good-Turing 估計 ?編輯 2.Back-off (后備/后退)方法 3.絕對減值法 ?編輯4.線性減值法 5.比較 三.刪除插值法(Deleted interpolation) 四.模型自適應 引言 本章節講的…

SpringAI Alibaba實戰文生圖

1?? 前置準備&#xff1a;搭建開發環境與服務配置&#x1f680; &#x1f527; 1.1 環境要求 JDK 17&#xff08;推薦 JDK 21&#xff09;、Spring Boot 3.x&#xff08;本案例使用 3.3.4&#xff09;、阿里云百煉大模型服務 API Key。需在阿里云控制臺完成服務開通并獲取有…

實戰二:開發網頁端界面完成黑白視頻轉為彩色視頻

?一、需求描述 設計一個簡單的視頻上色應用&#xff0c;用戶可以通過網頁界面上傳黑白視頻&#xff0c;系統會自動將其轉換為彩色視頻。整個過程對用戶來說非常簡單直觀&#xff0c;不需要了解技術細節。 效果圖 ?二、實現思路 總體思路&#xff1a; 用戶通過Gradio界面上…

Kotlin List 操作全面指南

在傳統 Java 開發 List 相關的 API 中&#xff0c;有著樣板代碼冗長、缺乏鏈式調用、空安全等問題。 Kotlin 這門語言 為 List 提供了豐富的擴展函數&#xff0c;這些函數大大簡化了集合操作&#xff0c;解決了傳統 Java 集合 API 中的許多痛點。 一、基礎操作 1. 創建 List …

硬盤尋址全解析:從 CHS 三維迷宮到 LBA 線性王國

在數字存儲的底層世界&#xff0c;硬盤如同一個巨大的 “數據圖書館”&#xff0c;而尋址模式就是決定如何高效找到 “書籍”&#xff08;扇區&#xff09;的核心規則。從早期基于物理結構的 CHS&#xff08;柱面 - 磁頭 - 扇區&#xff09;三維尋址&#xff0c;到現代抽象化的…

oracle 11g ADG備庫報錯ORA-00449 lgwr unexpectedly分析處理

問題背景 昨天遇到群友提問&#xff0c;遇到ADG備庫掛了的情況 數據版本:11.2.0.4 操作系統:Centos7.9 環境&#xff1a;ADG主備庫&#xff0c;主庫為RAC&#xff0c;備庫也是RAC 具體報錯ORA-00449以及ORA-04021 看樣子是LGWR掛了&#xff0c;還有個鎖等待。 問題分析 先…