C語言是面向過程,關注的是過程,分析出求解問題的步驟,通過函數調用逐步解決問題,而C++面向的是對象,關注的是對象,將一件事拆解成多個對象,靠對象之間互交完成。
目錄
類的定義
類的兩種定義
類的訪問限定符及封裝
struct和class的區別:
類的作用域
封裝
類的實例化
類的對象大小
this指針
this指針的特性?
類的定義
#include<iostream>
using namespace std;class className
{// 類體:由成員函數和成員變量組成}; // 一定要注意后面的分號
class為定義類的關鍵字,className是類名,可以自己定義,括號里面就是類體:由成員函數和成員變量組成,括號后面需要帶分號。
類體中內容稱為類的成員:類中的變量稱為類的屬性或成員變量; 類中的函數稱為類的方法或者 成員函數。 ?
類的兩種定義
第一種定義方式:將函數聲明和定義都放類體中,需注意:成員函數如果在類中定義,編譯器可能會將其當成內 聯函數處理。
示例:
#include<iostream>
using namespace std;class student {
public:void print(){cout << age << endl;}
private:int age;
};
第二種定義:類聲明放在頭文件.h中,函數的定義在類中放在源文件.cpp中。注意:成員函數名前需要加類名::?
這里有一個變量命名的建議:
?在聲明變量時在前面加一個_更方便理解,不然在初始化時都使用age名稱容易混淆,在上面代碼中_age是聲明的變量,age是形參,將形參的值賦給聲明的變量_age。
類的訪問限定符及封裝
C++實現封裝的方式:用類將對象的屬性與方法結合在一塊,讓對象更加完善,通過訪問權限選 擇性的將其接口提供給外部的用戶使用。
訪問限定符說明:
1. public修飾的成員在類外可以直接被訪問
2. protected和private修飾的成員在類外不能直接被訪問(此處protected和private是類似的)
3. 訪問權限作用域從該訪問限定符出現的位置開始直到下一個訪問限定符出現時為止
4. 如果后面沒有訪問限定符,作用域就到 } 即類結束。
5. class的默認訪問權限為private,struct為public(因為struct要兼容C)
注意:訪問限定符只在編譯起作用,當數據映射到內存上時,就訪問限定符沒有區別。
struct和class的區別:
struct?里也可以聲明和定義函數,因為c++要兼容c,而在class中如果不加任何訪問限定符默認的就是private(私有的),在struct中默認是public(共有的)。
類的作用域
類定義了一個新的作用域,類的所有成員都在類的作用域中。如果出了類的作用域定義函數就需要再函數前加::作用域限定符。
示例:
#include<iostream>
using namespace std;class student {
public:void Init(int age);
private:int _age;
};void student::Init(int age)
{_age = age;
}
封裝
封裝:將數據和操作數據的方法有機結合,隱藏對象的屬性和實現細節,僅對外公開接口來實現和對象互交。
封裝本質上是一種管理,讓用戶更方便操作類。
在C++語言中實現封裝,可以通過類將數據以及操作數據的方法進行有機結合,通過訪問權限來 隱藏對象內部實現細節,控制哪些方法可以在類外部直接被使用。
類的實例化
用類類型來創建對象,叫做類的實例化。
在還沒有創建對象時,定義一個類并沒有分配實際的空間,就像是一個模型一樣,當創建一個或者多個對象才會分配空間。
類的對象大小
示例:
#include<iostream>
using namespace std;class A {
public:void print(){cout << "A" << endl;}
private:char _a;
};int main()
{A a;cout << sizeof(a) << endl;return 0;
}
上面代碼對象a的大小為多少呢?函數會不會算在里面呢?
看看運行結果:
?結果對象a的大小為1,只算了_a的大小,那函數大小不算的嗎?事實上就是不算函數的大小,函數放在公共的代碼區,每個創建的對象都可以去公共代碼區調用函數,當然計算類的大小時還需要注意內存對齊規則,和結構體內存對齊規則是一樣的。
當這個類只有函數或者為空類時,大小為1,那為什么不是0呢?如果類中只有函數或者為空類的大小為0,那么就在內存中沒有地址,那怎么找到類中的地址呢?沒有成員變量的類對象,需要1byte,是為了占位,表示對象存在。所以一個類的大小,實際就是該類中”成員變量”之和,當然要注意內存對齊 注意空類的大小,空類比較特殊,編譯器給了空類一個字節來唯一標識這個類的對象。
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(2022, 1, 11);d2.Init(2022, 1, 12);d1.Print();d2.Print();return 0;
}
?為什么創建兩個對象去調用Print可以輸出不同的結果?
在這里就用了this指針,C++編譯器給每個“非靜態的成員函數“增加了一個隱藏 的指針參數,讓該指針指向當前對象(函數運行時調用該函數的對象),在函數體中所有“成員變量” 的操作,都是通過該指針去訪問。只不過所有的操作對用戶是透明的,即用戶不需要來傳遞,編譯器自動完成。
注意:this指針不能再形參和實參顯示傳遞,但是可以在函數內部中使用
?示例:
class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << this->_year << "-" << this->_month << "-" << this->_day << endl;}
private:int _year;int _month;int _day;
};int main()
{Date d1, d2;d1.Init(2022, 1, 11);d2.Init(2022, 1, 12);d1.Print();d2.Print();return 0;
}
this指針的特性?
1. this指針的類型:類類型* const,即成員函數中,不能給this指針賦值。
2. 只能在“成員函數”的內部使用
3. this指針本質上是“成員函數”的形參,當對象調用成員函數時,將對象地址作為實參傳遞給 this形參。所以對象中不存儲this指針。
4. this指針是“成員函數”第一個隱含的指針形參,一般情況由編譯器通過ecx寄存器自動傳 遞,不需要用戶傳遞
?this指針存放在棧中,因為它是形參,在進入一個函數時需要先對形參壓棧,所以this指針存放在棧中。this在不需要解引用的情況下可以為空,否則不可以為空。