邯鄲網(wǎng)站建設(shè)哪家好windows優(yōu)化大師怎么使用
類和對象(1)
- 一、類的相關(guān)內(nèi)容
- 1.訪問限定符
- 2.class關(guān)鍵字與struct關(guān)鍵字的區(qū)別
- 3.類域
- 二、this指針
- 三、成員函數(shù)存放在哪里?
- 1. 函數(shù)的存放位置
- 2. 練習題
一、類的相關(guān)內(nèi)容
1.訪問限定符
(1)C++?種實現(xiàn)封裝的?式,?類將對象的屬性與?法結(jié)合在?塊,讓對象更加完善,通過訪問權(quán)限選擇性的將其接?提供給外部的??使?。
(2)public修飾的成員在類外可以直接被訪問;protected和private修飾的成員在類外不能直接被訪
問,protected和private是?樣的,以后繼承章節(jié)才能體現(xiàn)出他們的區(qū)別。
(3)訪問權(quán)限作?域從該訪問限定符出現(xiàn)的位置開始直到下?個訪問限定符出現(xiàn)時為?,如果后?沒有訪問限定符,作?域就到 }即類結(jié)束。
(4)class定義成員沒有被訪問限定符修飾時默認為private,struct默認為public。
(5)?般成員變量都會被限制為private/protected,需要給別?使?的成員函數(shù)會放為public。
2.class關(guān)鍵字與struct關(guān)鍵字的區(qū)別
(1)class為定義類的關(guān)鍵字,后面跟類的名字,{}中為類的主體,注意類定義結(jié)束時后?分號不能省
略。類體中內(nèi)容稱為類的成員;類中的變量稱為類的屬性或成員變量; 類中的函數(shù)稱為類的?法或
者成員函數(shù)。
(2)C++中struct也可以定義類,C++兼容C中struct的?法,同時struct升級成了類,明顯的變化是
struct中可以定義函數(shù)。
#include<iostream>
using namespace std;
// C++升級struct升級成了類
// 1、類??可以定義函數(shù)
// 2、struct名稱就可以代表類型
// C++兼容C中struct的?法//這是c語言結(jié)構(gòu)體的定義:ListNodeC不能代表類型,要加上struct關(guān)鍵字,除非typedef
typedef struct ListNodeC
{struct ListNodeC* next;int val;
}LTNode;// 不再需要typedef,ListNodeCPP就可以代表類型
struct ListNodeCPP
{void Init(int x){next = nullptr;val = x;}ListNodeCPP* next;int val;
};
int main()
{return 0;
}
3.類域
(1)類定義了?個新的作?域,類的所有成員都在類的作?域中,在類體外定義成員時,需要使? :: 作?域操作符指明成員屬于哪個類域。
(2)類域影響的是編譯的查找規(guī)則,下?程序中Init如果不指定類域Stack,那么編譯器就把Init當成全
局函數(shù),那么編譯時,找不到array等成員的聲明/定義在哪?,就會報錯。指定類域Stack,就是知
道Init是成員函數(shù),當前域找不到的array等成員,就會到類域中去查找。
#include<iostream>
using namespace std;
class Stack
{
public:
// 成員函數(shù)void Init(int n = 4);
private:
// 成員變量int* array;size_t capacity;size_t top;
};
// 聲明和定義分離,需要指定類域
void Stack::Init(int n) //缺省值只能在聲明定義
{array = (int*)malloc(sizeof(int) * n);if (nullptr == array){perror("malloc申請空間失敗");return;}capacity = n;top = 0;
}
int main()
{Stack st;st.Init();return 0;
}
二、this指針
(1)Date類中有 Init 與 Print 兩個成員函數(shù),函數(shù)體中沒有關(guān)于不同對象的區(qū)分,而且成員函數(shù)并不屬于某一個對象,同類的所有對象共享一份成員函數(shù)。那當d1調(diào)?Init和Print函數(shù)時,該函數(shù)是如何知道應(yīng)該訪問的是d1對象還是d2對象呢?那么這?就要看到C++給了?個隱含的this指針解決這?的問題。
(2)編譯器編譯后,類的成員函數(shù)默認都會在形參第?個位置,增加?個當前類類型的指針,叫做this
指針。?如Date類的Init的真實原型為, void Init(Date* const this, int year,int month, int day)。
(3)類的成員函數(shù)中訪問成員變量,本質(zhì)都是通過this指針訪問的,如Init函數(shù)中給_year賦值,
this->_year = year。
(4)C++規(guī)定不能在實參和形參的位置顯?的寫this指針(編譯時編譯器會處理),但是可以在函數(shù)體內(nèi)顯?使?this指針。
#include<iostream>
using namespace std;
class Date
{
public:
// void Init(Date* const this, int year, int month, int day)
void Init(int year, int month, int day)
{//注意:this指針只能指向當前對象
// 編譯報錯:error C2106: “=”: 左操作數(shù)必須為左值
// this = nullptr;_year = year;this->_month = month;this->_day = day;
}
void Print()
{cout << _year << "/" << _month << "/" << _day << endl;
}
private:// 這?只是聲明,沒有開空間int _year;int _month;int _day;
};
int main()
{
// Date類實例化出對象d1和d2Date d1;Date d2;
// d1.Init(&d1, 2024, 3, 31);d1.Init(2024, 3, 31);d1.Print();d2.Init(2024, 7, 5);d2.Print();return 0;
}
三、成員函數(shù)存放在哪里?
1. 函數(shù)的存放位置
- 代碼段存儲:
無論是全局函數(shù)、靜態(tài)成員函數(shù)、const成員函數(shù)還是普通成員函數(shù),在編譯后都會被放置在代碼段中。這是因為函數(shù)代碼是共享資源,不需要為每個對象實例都復(fù)制一份,更不會直接存儲在對象的內(nèi)存布局中。 - 對象不存儲函數(shù)代碼:
當我們創(chuàng)建一個類的對象時,對象本身只包含其數(shù)據(jù)成員和可能的虛函數(shù)表指針(如果類包含虛函數(shù))。成員函數(shù)代碼并不存儲在對象中。 - this指針的作用:
當成員函數(shù)被調(diào)用時,編譯器會自動傳遞一個指向調(diào)用對象的指針,即this指針。這個指針使得成員函數(shù)能夠訪問和修改對象的數(shù)據(jù)成員。this指針并不是成員函數(shù)的存儲位置,而是函數(shù)訪問對象數(shù)據(jù)成員的橋梁。 - 虛函數(shù)和虛函數(shù)表:
如果類包含虛函數(shù),編譯器會為每個包含虛函數(shù)的類生成一個虛函數(shù)表(vtable)。虛函數(shù)表包含了指向虛函數(shù)實現(xiàn)的指針。對象實例中包含一個指向其所屬類的虛函數(shù)表的指針(vptr)。當通過基類指針或引用調(diào)用虛函數(shù)時,會根據(jù)虛函數(shù)表找到正確的函數(shù)實現(xiàn)進行調(diào)用。(詳情看多態(tài)一節(jié))。
例如:
匯編角度:
2. 練習題
#include<iostream>
using namespace std;
class A
{
public:void Print(){cout << "A::Print()" << endl;}
private:int _a;
};
int main()
{A* p = nullptr;p->Print();return 0;
}