類和對象深入理解

目錄

  • static成員
    • 概念
      • 靜態成員變量
        • 面試題
        • 補充
          • 代碼1
          • 代碼2
          • 代碼3
          • 如何訪問private中的成員變量
      • 靜態成員函數
        • 靜態成員函數沒有this指針
    • 特性
  • 友元
    • 友元函數
    • 友元類
  • 內部類
    • 特性1
    • 特性2
  • 匿名對象
  • 拷貝對象時的一些編譯器優化

感謝各位大佬對我的支持,如果我的文章對你有用,歡迎點擊以下鏈接
🐒🐒🐒 個人主頁
🥸🥸🥸 C語言
🐿?🐿?🐿? C語言例題
🐣🐣🐣 python
🐓🐓🐓 數據結構C語言
🐔🐔🐔 C++
🐿?🐿?🐿? 文章鏈接目錄

static成員

概念

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

靜態成員變量

面試題

面試題:實現一個類,計算程序中創建出了多少個類對象。

class A
{
public:A(){++n;}A(const A& aa){++ n;}
private:static int n;
}; 
int A::n = 0;

這里的n就是一個靜態全局變量,注意靜態變量是不能給缺省值的,因為他不是單獨屬于某一個對象,而是屬于這個類的所有對象,因此需要在類外面定義

由于n受域作用限定符的限制,當我們屏蔽掉private后就可以訪問n了
在這里插入圖片描述

我們再來看看下面的三段代碼

補充
代碼1
class A
{
public:A(){++n;}A(const A& aa){++ n;}
//private:static int n;
}; 
int A::n = 0;
int main()
{A aa1;A aa2;A* ptr = nullptr;cout << aa1.n << endl;cout << aa2.n << endl;cout << ptr->n << endl;return

在這里插入圖片描述

代碼2
class A
{
public:A(){++n;}A(const A& aa){++ n;}
//private:static int n;
}; 
int A::n = 0;
int main()
{A aa1;//A aa2;A* ptr = nullptr;cout << aa1.n << endl;//cout << aa2.n << endl;cout << ptr->n << endl;return 0;
}

在這里插入圖片描述

代碼3
class A
{
public:A(){++n;}A(const A& aa){++ n;}
//private:static int n;
}; 
int A::n = 0;
int main()
{//A aa1;//A aa2;A* ptr = nullptr;//cout << aa1.n << endl;//cout << aa2.n << endl;cout << ptr->n << endl;return 0;
}

在這里插入圖片描述
上面的三個代碼中ptr輸出的n的值是不一樣的,這需要我們了解static存儲的變量在靜態區
比如ptr->n,n并不在ptr指向的對象里,而是在靜態區,在尋找n的時候就是去靜態區里找
因為是受到static修飾,所以n的值是全局變量,全局變量不想局部變量,出了作用域后就會銷毀然后從新開始,也就是說這里的n不會因為一個對象結束后就重新變成0

如何訪問private中的成員變量

上面的代碼中我們都是將private屏蔽掉才可以訪問到n的,當private沒有屏蔽的時候,就會因為權限導出不允許訪問
在這里插入圖片描述
要想解決這個問題只有在公有區域里創建一個函數Getn()去獲得n的值

class A
{
public:A(){++n;}A(const A& aa){++ n;}int Getn(){return n;}
private:static int n;
}; 
int A::n = 0;
int main()
{A aa1;cout << aa1.Getn() << endl;return 0;
}

在這里插入圖片描述

靜態成員函數

靜態成員函數的訪問方式如下
在這里插入圖片描述
A::Getn()也是可以這樣訪問的,另外靜態成員變量也同理
在這里插入圖片描述

靜態成員函數沒有this指針

靜態成員函數與普通的成員函數不同點在于靜態成員函數沒有this指針,所以不能訪問非靜態成員變量或者函數

class A
{
public:A(){++n;}A(const A& aa){++ n;}static int Getn(){a++;return n;}
private:static int n;int a;
}; 
int A::n = 0;
int main()
{A aa1;cout << A::n << endl;return 0;
}

在這里插入圖片描述

特性

1. 靜態成員為所有類對象所共享,不屬于某個具體的對象,存放在靜態區
2. 靜態成員變量必須在類外定義,定義時不添加static關鍵字,類中只是聲明
3. 類靜態成員即可用 類名::靜態成員 或者 對象.靜態成員 來訪問
4. 靜態成員函數沒有隱藏的this指針,不能訪問任何非靜態成員
5. 靜態成員也是類的成員,受public、protected、private 訪問限定符的限制

友元

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

友元函數

問題:
現在嘗試去重載operator<<,然后發現沒辦法將operator<<重載成成員函數
因為cout的輸出流對象和隱含的this指針在搶占第一個參數的位置。this指針默認是第一個參數也就是左操作數了。
但是實際使用中cout需要是第一個形參對象,才能正常使用
所以要將operator<<重載成全局函數。但又會導致類外沒辦法訪問成員,此時就需要友元來解決。operator>>同理。

class Date
{
public:Date(int year, int month, int day): _year(year), _month(month), _day(day){}// d1 << cout; -> d1.operator<<(&d1, cout); 不符合常規調用// 因為成員函數第一個參數一定是隱藏的this,所以d1必須放在<<的左側ostream& operator<<(ostream& _cout){_cout << _year << "-" << _month << "-" << _day << endl;return _cout;}
private:int _year;int _month;int _day;
};

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

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;return 0;
}

說明:
友元函數可訪問類的私有和保護成員,但不是類的成員函數
友元函數不能用const修飾(沒有this指針)
友元函數可以在類定義的任何地方聲明,不受類訪問限定符限制
一個函數可以是多個類的友元函數
友元函數的調用與普通函數的調用原理相同

友元類

友元類的所有成員函數都可以是另一個類的友元函數,都可以訪問另一個類中的非公有成員。
友元關系是單向的,不具有交換性。
比如上述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. sizeof(外部類)=外部類,和內部類沒有任何關系。
2. 內部類可以定義在外部類的public、protected、private都是可以的,且內部類受類域限制
3. 注意內部類可以直接訪問外部類中的static成員,不需要外部類的對象/類名(內部類是外部類的友元類)

特性1

class A
{
private:static int k;int h;
public:class B // B天生就是A的友元{public:void foo(const A& a){cout << k << endl;cout << a.h << endl;}};
};
int A::k = 1;
int main()
{A::B b;b.foo(A());cout << sizeof(A) << endl;return 0;
}

在這里插入圖片描述

sizeof(A)的結果是4,可能很多人會覺得B在A里面的,所以sizeof(A)的結果是包含了B的空間的,但是事實上不是這樣的,如果要讓sizeof(A)的結果是算上B的空間大小的話應該像下面這段代碼這樣寫

class B
{
private:int _b1;
};
class A
{
private:static int k;int h;B _b;
}

此外類是不占用空間的,因為類只是一個聲明,而在定義的時候才會有空間,也就是說聲明只是說有這么一個東西,但是不會講空間分配給他,而定義則是讓這個東西真實的存在,并分配空間給他

特性2

內部類也是受訪問限定符和類域的限制

class A
{
public:class B{};
};
int main()
{A a;B b;return 0;
}

在這里插入圖片描述
當我們用域作用限定符的時候就可以正常運行

class A
{
public:class B{};
};
int main()
{A a;A::B b;return 0;
}

在這里插入圖片描述
但是當class B 在A的private中就會因為B是私有導致無法訪問

class A
{
private:class B{};
};
int main()
{A a;A::B b;return 0;
}

在這里插入圖片描述

匿名對象

匿名對象就是沒有名字的對象,他的特點是生命周期只在當前一行

class A
{
public:A(int a = 0):_a(a){cout << "A(int a)" <<a<< endl;}~A(){cout << "~A()" << endl;}
private:int _a;
};
int main()
{A aa1;A aa2(2);A();A(3);return 0;
}

在這里插入圖片描述

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

在傳參和傳返回值的過程中,一般編譯器會做一些優化,減少對象的拷貝,這個在一些場景下還
是非常有用的。
但是不同的編譯器優化程度是不同的,所以我們只需要簡單了解一下就可以了

class A
{
public:A(int a = 0):_a(a){cout << "A(int a)" << endl;}A(const A& aa):_a(aa._a){cout << "A(const A& aa)" << endl;}A& operator=(const A& aa){cout << "A& operator=(const A& aa)" << endl;if (this != &aa){_a = aa._a;}return *this;}~A(){cout << "~A()" << endl;}
private:int _a;
};
void f1(A aa)
{}
A f2()
{A aa;return aa;
}
int main()
{// 傳值傳參A aa1;f1(aa1);cout << endl;// 傳值返回f2();cout << endl;// 隱式類型,連續構造+拷貝構造->優化為直接構造f1(1);// 一個表達式中,連續構造+拷貝構造->優化為一個構造f1(A(2));cout << endl;// 一個表達式中,連續拷貝構造+拷貝構造->優化一個拷貝構造A aa2 = f2();cout << endl;// 一個表達式中,連續拷貝構造+賦值重載->無法優化aa1 = f2();cout << endl;return 0;
}

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

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

相關文章

Linux-DNS

DNS域名解析服務 1.DNS介紹 DNS 是域名系統 (Domain Name System) 的縮寫&#xff0c;是因特網的一項核心服務&#xff0c;它作為可以將域名和IP地址相互映射的一個分布式數據庫&#xff0c;能夠使人更方便的訪問互聯網&#xff0c;而不用去記住能夠被機器直接讀取的IP數串。…

大氣熱力學(2)——熱力學基礎

本篇文章源自我在 2021 年暑假自學大氣物理相關知識時手寫的筆記&#xff0c;現轉化為電子版本以作存檔。相較于手寫筆記&#xff0c;電子版的部分內容有補充和修改。筆記內容大部分為公式的推導過程。 文章目錄 2.0 本文所用符號一覽2.1 準靜態過程2.2 熱量和熱容量2.2.1 熱量…

Java對象

面向對象和面向過程的區別 兩者的主要區別在于解決問題的方式不同 面向過程把解決問題的過程拆成一個個方法&#xff0c;通過一個個方法的執行解決問題。 面向對象會先抽象出對象&#xff0c;然后用對象執行方法的方式解決問題。 另外&#xff0c;面向對象開發的程序一般更易維…

乞丐傳武功

題目 你施舍給了路邊的乞丐兩個饅頭&#xff0c;誰料這個乞丐其實是隱士高人。為了回報你的善心&#xff0c;只見他緩緩從懷中掏出了數本武功秘籍&#xff0c;讓你從中挑選一本。你珍重地接過這些秘籍&#xff0c;目光掃過每本封面&#xff0c;降龍十八掌、神照經、易筋經、凌…

[FreeRTOS 基礎知識] 互斥量 概念

文章目錄 基礎知識互斥量互斥量與信號量區別優先級反轉優先級繼承小結 基礎知識 [FreeRTOS 基礎知識] 信號量 概念 互斥量 互斥量&#xff08;Mutex&#xff0c;全稱&#xff1a;Mutual Exclusion&#xff09;&#xff0c;在計算機科學中&#xff0c;是一種用于防止多個進程同…

科研繪圖系列:R語言實驗結果組圖(linechart + barplot)

介紹 實驗結果的多樣性意味著每個結果都可能揭示研究的不同方面或角度。在科學研究和數據分析中,通常我們會收集一系列數據點,每個數據點都對應著實驗的一個特定變量或條件。為了全面理解這些數據,我們可能會采用多種可視化技術來展示它們。 將多個結果分別可視化,可以讓…

親子時光里的打臉高手,賈乃亮與甜馨的父愛如山

賈乃亮這波操作&#xff0c;簡直是“實力打臉”界的MVP啊&#xff01; 7月5號&#xff0c;他一甩手&#xff0c;甩出張合照&#xff0c; 瞬間讓多少猜測紛飛的小伙伴直呼&#xff1a;“臉疼不&#xff1f;”帶著咱家小甜心甜馨&#xff0c; 回了哈爾濱老家&#xff0c;這趟親…

Nginx(http配置、https配置)訪問Spring Boot 項目

前文 記錄一下在linux服務器下配置nginx中nginx.conf文件代理訪問springboot項目 1. spring boot.yml配置 其他mysql,redis,mybatis等之類的配置就不一一列出了 # 自定義配置 為了等下驗證讀取的配置文件環境 appName: productserver:port: 8083 # 應用服務 WEB 訪問端口s…

SQL窗口函數詳解

詳細說明在sql中窗口函數是什么&#xff0c;為什么需要窗口函數&#xff0c;有普通的聚合函數了那窗口函數的意義在哪&#xff0c;窗口函數的執行邏輯是什么&#xff0c;over中的字句是如何使用和理解的&#xff08;是不是句句戳到你的痛點&#xff0c;哼哼&#xff5e;&#x…

C語言編譯和編譯預處理

編譯預處理 ? 編譯是指把高級語言編寫的源程序翻譯成計算機可識別的二進制程序&#xff08;目標程序&#xff09;的過程&#xff0c;它由編譯程序完成。 ? 編譯預處理是指在編譯之前所作的處理工作&#xff0c;它由編譯預處理程序完成 在對一個源程序進行編譯時&#xff0c;…

全國青少年軟件編程等級考試-四級-奇偶之和(真題)

題目&#xff1a;奇偶之和 1.準備工作 (1)保留舞臺中的小貓角色&#xff1b; 2.功能實現 (1)分別計算1&#xff5e;100中&#xff0c;奇數之和&#xff0c;偶數之和&#xff1b; (2)說出奇數之和&#xff0c;偶數之和。 講解&#xff1a; 1、如何判斷奇偶數 奇數是指除以2有…

C++deque容器

文章目錄 deque容器概念deque操作deque對象的帶參數構造deque頭部和末尾的添加移除操作deque的數據存取deque與迭代器deque賦值deque插入deque刪除 deque容器概念 deque是雙端數組&#xff0c;而vector是單端的。 ?deque頭部和尾部添加或移除元素都非常快速, 但是在中部安插元…

在x86/amd64的機器上使用Docker運行arm64v8/ubuntu并安裝ROS1

一、準備工作 主要是因為國內網絡的問題&#xff0c;可能導致鏡像拉取失敗&#xff0c;解決辦法參考&#xff1a;鏡像加速 二、安裝運行過程 2.1拉取鏡像&#xff1a; sudo docker pull arm64v8/ubuntu:20.04這個是ubuntu的拉取指令&#xff0c;其他的也是類似。 2.2 運行…

【DevOps】運維過程中經常遇到的Http錯誤碼問題分析(一)

一、解決HTTP 408錯誤&#xff1a;上傳3M文件時請求超時的問題 在開發Web應用程序時&#xff0c;遇到HTTP 408狀態碼&#xff08;請求超時&#xff09;是常見的問題。特別是在上傳大文件時&#xff0c;這種情況更容易發生。本文將探討在上傳一個3M文件時&#xff0c;Web服務器…

LeetCode題練習與總結:排序鏈表--148

一、題目描述 給你鏈表的頭結點 head &#xff0c;請將其按 升序 排列并返回 排序后的鏈表 。 示例 1&#xff1a; 輸入&#xff1a;head [4,2,1,3] 輸出&#xff1a;[1,2,3,4]示例 2&#xff1a; 輸入&#xff1a;head [-1,5,3,4,0] 輸出&#xff1a;[-1,0,3,4,5]示例 3&am…

封鎖-封鎖模式(共享鎖、排他鎖)、封鎖協議(兩階段封鎖協議)

一、引言 1、封鎖技術是目前大多數商用DBMS采用的并發控制技術&#xff0c;封鎖技術通過在數據庫對象上維護鎖來實現并發事務非串行調度的沖突可串行化 2、基于鎖的并發控制的基本思想是&#xff1a; 當一個事務對需要訪問的數據庫對象&#xff0c;例如關系、元組等進行操作…

【嵌入式開發 Linux 常用命令系列 1.6 -- grep 過濾指定的目錄】

請閱讀【嵌入式開發學習必備專欄 】 文章目錄 grep 過濾指定目錄 grep 過濾指定目錄 在Linux中使用grep搜索字符串并希望排除特定目錄時&#xff0c;可以使用--exclude-dir參數。這個參數允許你指定一個或多個目錄名稱來排除它們的內容不被grep搜索。這對于忽略一些常見的臨時…

LLM - 詞向量 Word2vec

1. 詞向量是一個詞的低維表示&#xff0c;詞向量可以反應語言的一些規律&#xff0c;詞意相近的詞向量之間近乎于平行。 2. 詞向量的實現&#xff1a; &#xff08;1&#xff09;首先使用滑動窗口來構造數據&#xff0c;一個滑動窗口是指在一段文本中連續出現的幾個單詞&#x…

llamaindex實戰-使用本地大模型和數據庫對話

概述 本文使用NLSQLTableQueryEngine 查詢引擎來構建SQL的自然語言處理查詢。 請注意&#xff0c;我們需要指定要與該查詢引擎一起使用的表。如果我們不這樣做&#xff0c;查詢引擎將提取所有架構上下文&#xff0c;這可能會溢出 LLM 的上下文窗口。 在以下情況都可以使用NL…

如何用Java寫一個整理Java方法調用關系網絡的程序

大家好&#xff0c;我是猿碼叔叔&#xff0c;一位 Java 語言工作者&#xff0c;也是一位算法學習剛入門的小學生。很久沒有為大家帶來干貨了。 最近遇到了一個問題&#xff0c;大致是這樣的&#xff1a;如果給你一個 java 方法&#xff0c;如何找到有哪些菜單在使用。我的第一想…