📝個人主頁🌹:EterNity_TiMe_
?收錄專欄?:C++ “ 登神長階 ”
🌹🌹期待您的關注 🌹🌹
類和對象
- 1. 初步認識C++
- 2. 類的引入
- 3. 類的定義
- 聲明和定義全部放在類體中
- 聲明和定義分開存放
- 4. 類的訪問限定符
- 5. 類的實例化
- 6. 類對象模型
- 如何計算類對象的大小
- 類對象的存儲方式
- 7. this指針
- this指針的特性
- 8. 總結
前言:在前面幾節我們為正式進入C++做足了鋪墊,現在我們有了足夠的基礎讓我們進入C++,讓我們來進入類和對象來真正了解C++!
本篇主要內容:
類的相關知識
this指針
1. 初步認識C++
1. 我們知道之前學習的C語言是面向過程的,關注的是過程,分析出求解問題的步驟,通過函數調用逐步解決問題。
2. C++是基于面向對象的,關注的是對象,將一件事情拆分成不同的對象,靠對象之間的交互完成
舉個例子,就像我們洗衣服,在C語言中我們需要一步一步按過程操作來手洗,而C++則是有了很多對象,對象間相互交互來完成洗衣服!
2. 類的引入
C語言結構體中只能定義變量,不可以定義函數,但是在C++中,結構體內不僅可以定義變量,也可以定義函數。
struct pxt
{char b[100] = { "hello world!" };int a = 2024;void test(){cout << "hello world!" << endl;}};
int main()
{pxt xyyj;xyyj.test();cout << xyyj.b << endl;return 0;
}
上面結構體的定義就是類,但在C++中更喜歡用class來代替
3. 類的定義
// C++中更喜歡用class
class className
{// 類體:由成員函數和成員變量組成
};
// 一定要注意后面的分號
- class為定義類的關鍵字,className為類的名字,{}中為類的主體,注意類定義結束時后面分號不能省略
- 類體中內容稱為類的成員:類中的變量稱為類的屬性或成員變量; 類中的函數稱為類的方法或者成員函數
類的兩種定義方式:
- 聲明和定義全部放在類體中
- 聲明和定義分開存放
聲明和定義全部放在類體中
class pxt
{int a = 2024;char b[100] = { "hello world!" };int c = 666;void test(){cout << b << " " << a << " " << c << endl;}
};
int main()
{pxt xyyj;xyyj.test();return 0;
}
注意: 成員函數如果在類中定義,編譯器可能會將其當成內聯函數處理。
聲明和定義分開存放
// func.h
class pxt
{int a = 2024;char b[100] = { "hello world!" };int c = 666;void test();
};
// func.cpp
void test()
{cout << b << " " << a << " " << c << endl;
}
// test.c
int main()
{pxt xyyj;xyyj.test();return 0;
}
如果這樣聲明和定義那么將無法完成編譯!
test在func.cpp中找不到pxt類中的成員變量
// 因此我們應該指明在pxt中尋找,否則可能以為定義一個新函數
void pxt::test()
{cout << b << " " << a << " " << c << endl;
}
4. 類的訪問限定符
訪問限定符說明:
- public修飾的成員在類外可以直接被訪問
- protected和private修飾的成員在類外不能直接被訪問(此處protected和private是類似的)
- 訪問權限作用域從該訪問限定符出現的位置開始直到下一個訪問限定符出現時為止
- 如果后面沒有訪問限定符,作用域就到最后即類結束。
- class的默認訪問權限為private,struct為public(因為struct要兼容C)
class pxt
{
public:void test(){cout << b << " " << a << " " << c << endl;}
private:int a;char b[100] = { "hello world!" };int c;
};
int main()
{pxt xyyj;xyyj.test();//cout << xyyj.b << endl; // 無法運行//cout << xyyj.a << endl; // 無法運行return 0;
}
public修飾的成員是共有的,類外可以訪問
private修飾的的成員是私有的類外不能訪問
注意:成員函數不管成員變量是私有還是公有,它都能直接訪問,因為它們都屬于這個類
5. 類的實例化
用類類型創建對象的過程,稱為類的實例化
- 類是對對象進行描述的,定義出一個類并沒有分配實際的內存空間來存儲它
- 實例化出的對象 占用實際的物理空間,存儲類成員變量
// 在沒有實例化之前并不會占用實際物理空間
class pxt
{
public:......
private:int a;
};
類實例化出對象就像現實中使用建筑設計圖建造出房子,類就像是設計圖
6. 類對象模型
如何計算類對象的大小
class pxt
{
public:void test(){cout << b << " " << a << endl;}
private:int a;char b;
};
class xyyj
{
public:int a;char b;
};
int main()
{cout << "pxt -> sizeof: " << sizeof(pxt) << endl;cout << "xyyj -> sizeof: " << sizeof(xyyj) << endl;return 0;
}
在學C語言結構體的時候我們講過結構體內存對齊規則,那么C++中多了個函數該怎么計算呢,我們先來看看結果
初步結論:
- 類的成員函數不算在類的大小中
- 類的大小遵守結構體內存對齊規則
類對象的存儲方式
好家伙,兩個類結果居然是一樣的,這到底是什么情況?為啥類中的成員函數不占空間?
這其實和類對象的存儲方式有關——只保存成員變量,成員函數存放在公共的代碼段
每個對象雖然實例化的值不一樣,但是調用的函數是相同的,將函數單獨放在一個區域能節省空間
綜上所述:
- 類的成員函數不算在類的大小中
- 類的大小遵守結構體內存對齊規則
- 空類的大小是一個字節,用來唯一標識這個類的對象
忘了結構體內存對齊的可以復習一下:
結構體內存對齊
7. this指針
我們先來定義一個日期類:
class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year; // 年int _month; // 月int _day; // 日
};
int main()
{Date d1, d2;d1.Init(2024, 5, 20);d2.Init(2024, 5, 21);d1.Print();d2.Print();return 0;
}
那么Date類中有 Init 與 Print 兩個成員函數,函數體中沒有關于不同對象的區分,那當d1調用 Init 函數時,該函數是如何知道應該設置d1對象,而不是設置d2對象呢?
- C++編譯器給每個“非靜態的成員函數“增加了一個隱藏的指針參數,讓該指針指向當前對象(調用該函數的對象),在函數體中所有“成員變量”的操作,都是通過該指針去訪問
this指針的特性
this指針的特性:
- this指針的類型:類類型* const,即成員函數中,不能給this指針賦值。
- 只能在“成員函數”的內部使用
- this指針本質上是“成員函數”的形參,當對象調用成員函數時,將對象地址作為實參傳遞給this形參。所以對象中不存儲this指針。
- this指針是“成員函數”第一個隱含的指針形參,不需要用戶傳遞
雖然我們知道成員函數中存在this
指針,但是我們傳參不能傳this
指針
public:// 絕對不能這么定義void Init(Date*this, int year, int month, int day){_year = year;_month = month;_day = day;} // false
使用
this
指針將對象的地址傳入函數中函數體就可以區分不同對象了
8. 總結
本章是類和對象的第一課,我們簡單了解了類的基本概念和特性和this
指針,this
指針對后面用處很大,類在C++是很重要的希望大家能打好基礎!
謝謝大家支持本篇到這里就結束了