欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報激活碼778899分享:c語言 C++類和對象(上)

柚子快報激活碼778899分享:c語言 C++類和對象(上)

http://yzkb.51969.com/

??個人主頁:落葉

目錄

類的定義

類定義格式

訪問限定符

類域

實例化

實例化概念

對象??

this指針

C++和C語?實現(xiàn)Stack對?

C實現(xiàn)Stack代碼

C++實現(xiàn)Stack代碼

類的定義

類定義格式

class為定義類的關(guān)鍵字,Stack為類的名字,{}中為類的主體,注意類定義結(jié)束時后?分號不能省 略。類體中內(nèi)容稱為類的成員:類中的變量稱為類的屬性或成員變量;類中的函數(shù)稱為類的?法或 者成員函數(shù)。為了區(qū)分成員變量,?般習慣上成員變量會加?個特殊標識,如成員變量前?或者后?加_或者m 開頭,注意C++中這個并不是強制的,只是?些慣例,具體看公司的要求。C++中struct也可以定義類,C++兼容C中struct的?法,同時struct升級成了類,明顯的變化是 struct中可以定義函數(shù),?般情況下我們還是推薦?class定義類。定義在類?的成員函數(shù)默認為inline。

在類里,我們可以定義,成員變量和成員函數(shù),

#include

#include

class Stack

{

//成員函數(shù)

//成員變量

}; // 分號不能省略

下面這個代碼我們可以看到,棧的成員變量和成員函數(shù)。

#include

#include

class Stack

{

// 成員函數(shù)

//初始化

void Init(int n = 4)

{

array = (int*)malloc(sizeof(int) * n);

if (nullptr == array)

{

perror("malloc申請空間失敗");

return;

}

capacity = n;

top = 0;

}

//入棧

void Push(int x)

{

// ...擴容

array[top++] = x;

}

//出棧

int Top()

{

assert(top > 0);

return array[top - 1];

}

//銷毀

void Destroy()

{

free(array);

array = nullptr;

top = capacity = 0;

}

// 成員變量

int* array;

size_t capacity;

size_t top;

}; // 分號不能省略

class為定義類的關(guān)鍵字,Stack為類的名字,{}中為類的主體,注意類定義結(jié)束時后?分號不能省 略。類體中內(nèi)容稱為類的成員:類中的變量稱為類的屬性或成員變量;類中的函數(shù)稱為類的?法或 者成員函數(shù)。C++中struct也可以定義類,C++兼容C中struct的?法,同時struct升級成了類,明顯的變化是 struct中可以定義函數(shù),?般情況下我們還是推薦?class定義類。定義在類?的成員函數(shù)默認為inline。

為了區(qū)分成員變量,?般習慣上成員變量會加?個特殊標識,如成員變量前?或者后?加_或者m 開頭,注意C++中這個并不是強制的,只是?些慣例,具體看公司的要求。

class Date

{

public:

void Init(int year, int month, int day)

{

_year = year;

_month = month;

_day = day;

}

private:

// 為了區(qū)分成員變量,?般習慣上成員變量

// 會加?個特殊標識,如_ 或者 m開頭

int _year; // year_ m_year

int _month;

int _day;

};

int main()

{

Date d;

d.Init(2024, 3, 31);

return 0;

}

C++升級了struct升級成了類。

#include

using namespace std;

// C++升級struct升級成了類

// 1、類??可以定義函數(shù)

// 2、struct名稱就可以代表類型

// C++兼容C中struct的?法

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;

}

訪問限定符

C++?種實現(xiàn)封裝的?式,?類將對象的屬性與?法結(jié)合在?塊,讓對象更加完善,通過訪問權(quán)限選擇性的將其接?提供給外部的??使?。public修飾的成員在類外可以直接被訪問;protected和private修飾的成員在類外不能直接被訪問,protected和private是?樣的,以后繼承章節(jié)才能體現(xiàn)出他們的區(qū)別。訪問權(quán)限作?域從該訪問限定符出現(xiàn)的位置開始直到下?個訪問限定符出現(xiàn)時為?,如果后?沒有訪問限定符,作?域就到?}即類結(jié)束。class定義成員沒有被訪問限定符修飾時默認為private,struct默認為public。?般成員變量都會被限制為private/protected,需要給別?使?的成員函數(shù)會放為public。

?protected保護和私有是一樣的。

公有可以在class外使用或修改,私有class里面才能使用或修改。

#include

#include

class Stack

{

public://公有

// 成員函數(shù)

//初始化

void Init(int n = 4)

{

array = (int*)malloc(sizeof(int) * n);

if (nullptr == array)

{

perror("malloc申請空間失敗");

return;

}

capacity = n;

top = 0;

}

//入棧

void Push(int x)

{

// ...擴容

array[top++] = x;

}

//出棧

int Top()

{

assert(top > 0);

return array[top - 1];

}

//銷毀

void Destroy()

{

free(array);

array = nullptr;

top = capacity = 0;

}

private://私有

// 成員變量

int* array;

size_t capacity;

size_t top;

}; // 分號不能省略

類域

類定義了?個新的作?域,類的所有成員都在類的作?域中,在類體外定義成員時,需要使? :: 作?域操作符指明成員屬于哪個類域。類域影響的是編譯的查找規(guī)則,下?程序中Init如果不指定類域Stack,那么編譯器就把Init當成全局函數(shù),那么編譯時,找不到array等成員的聲明/定義在哪?,就會報錯。指定類域Stack,就是知道Init是成員函數(shù),當前域找不到的array等成員,就會到類域中去查找。

//Stack.h文件

#include

using namespace std;

class Stack

{

public:

// 成員函數(shù)

void Init(int n = 4);

private:

// 成員變量

int* array;

size_t capacity;

size_t top;

};

//Stack.cpp文件

// 聲明和定義分離,需要指定類域

void Stack::Init(int n)

{

array = (int*)malloc(sizeof(int) * n);

if (nullptr == array)

{

perror("malloc申請空間失敗");

return;

}

capacity = n;

top = 0;

}

//test.cpp文件

int main()

{

Stack st;

st.Init();

return 0;

}

在Stack.cpp文件中,聲明和定義分離,需要使? :: 作?域操作符指明成員屬于哪個類域,Stack這個域Stack:: ,這樣就可以找到這個函數(shù)了。

實例化

實例化概念

?類類型在物理內(nèi)存中創(chuàng)建對象的過程,稱為類實例化出對象。類是對象進??種抽象描述,是?個模型?樣的東西,限定了類有哪些成員變量,這些成員變量只是聲明,沒有分配空間,?類實例化出對象時,才會分配空間。?個類可以實例化出多個對象,實例化出的對象,占?實際的物理空間,存儲類成員變量。打個??:類實例化出對象就像現(xiàn)實中使?建筑設(shè)計圖建造出房?,類就像是設(shè)計圖,設(shè)計圖規(guī)劃了有多少個房間,房間??功能等,但是并沒有實體的建筑存在,也不能住?,?設(shè)計圖修建出房?,房?才能住?。同樣類就像設(shè)計圖?樣,不能存儲數(shù)據(jù),實例化出的對象分配物理內(nèi)存存儲數(shù)據(jù)。

d1和d2是不同的對象,它們的成員變量不是一樣的,就像上面這個圖一樣,

舉例:

一張房子的圖紙,可以建很多套房子,建成房子后才可以住人。

就像類是房子一樣,要實例化對象,才可以使用。

成員函數(shù)也不是存在類里的,是存在棧里的,當類實例化出多個對象后,多個對象調(diào)用的都是同一個,成員函數(shù)。

using namespace std;

class Date

{

public:

//成員函數(shù)

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

Date d1;

Date d2;

d1.Init(2024, 8, 6);

d2.Init(2025, 8, 7);

d1.Print();

d2.Print();

return 0;

}

對象??

分析?下類對象中哪些成員呢?類實例化出的每個對象,都有獨?的數(shù)據(jù)空間,所以對象中肯定包含成員變量,那么成員函數(shù)是否包含呢??先函數(shù)被編譯后是?段指令,對象中沒辦法存儲,這些指令存儲在?個單獨的區(qū)域(代碼段),那么對象中?要存儲的話,只能是成員函數(shù)的指針。再分析?下,對象中是否有存儲指針的必要呢,Date實例化d1和d2兩個對象,d1和d2都有各?獨?的成員變量_year/_month/_day存儲各?的數(shù)據(jù),但是d1和d2的成員函數(shù)Init/Print指針卻是?樣的,存儲在對象中就浪費了。如果?Date實例化100個對象,那么成員函數(shù)指針就重復存儲100次,太浪費了。這?需要再額外哆嗦?下,其實函數(shù)指針是不需要存儲的,函數(shù)指針是?個地址,調(diào)?函數(shù)被編譯成匯編指令[call地址],其實編譯器在編譯鏈接時,就要找到函數(shù)的地址,不是在運?時找,只有動態(tài)多態(tài)是在運?時找,就需要存儲函數(shù)地址,這個我們以后會講解。

上?我們分析了對象中只存儲成員變量,C++規(guī)定類實例化的對象也要符合內(nèi)存對?的規(guī)則。

內(nèi)存對?規(guī)則

第?個成員在與結(jié)構(gòu)體偏移量為0的地址處。其他成員變量要對?到某個數(shù)字(對?數(shù))的整數(shù)倍的地址處。注意:對?數(shù) = 編譯器默認的?個對?數(shù) 與 該成員??的較?值。VS中默認的對?數(shù)為8結(jié)構(gòu)體總??為:最?對?數(shù)(所有變量類型最?者與默認對?參數(shù)取最?)的整數(shù)倍。如果嵌套了結(jié)構(gòu)體的情況,嵌套的結(jié)構(gòu)體對?到??的最?對?數(shù)的整數(shù)倍處,結(jié)構(gòu)體的整體??就是所有最?對?數(shù)(含嵌套結(jié)構(gòu)體的對?數(shù))的整數(shù)倍。

我們來計算ABC實例化對象大小是多少。

using namespace std;

// 計算一下A/B/C實例化的對象是多大?

class A

{

public:

void Print()

{

cout << _ch << endl;

}

private:

char _ch;

int _i;

};

// 沒有成員變量的類對象,開1byte,占位,不存儲有效數(shù)據(jù)

// 標識對象的存在

class B

{

public:

void Print()

{

//...

}

};

class C

{};

int main()

{

A a;

B b;

C c;

cout << sizeof(a) << endl;

cout << sizeof(b) << endl;

cout << sizeof(c) << endl;

return 0;

}

A這個類,_ch是一個字節(jié)占用在0的位置,因為是按倍數(shù)來存的,int類型是4字節(jié)只能在4的倍數(shù)開始占用,

_i是4個字節(jié),從4開始往下占用4個字節(jié),大小是8個字節(jié)。

B這個類, 只有一個成員函數(shù),但是成員函數(shù)不是存放在類里的,是存放在棧里,所以成員函數(shù)不算類的大小。

沒有成員變量的類對象,開1byte,占位,不存儲有效數(shù)據(jù)標識對象的存在。

所以大小是1字節(jié)。

C這個類,沒有成員變量和成員函數(shù)

沒有成員變量的類對象,開1byte,占位,不存儲有效數(shù)據(jù)標識對象的存在。

所以大小是1字節(jié)。

上?的程序運?后,我們看到?jīng)]有成員變量的B和C類對象的??是1,為什么沒有成員變量還要給1個字節(jié)呢?因為如果?個字節(jié)都不給,怎么表?對象存在過呢!所以這?給1字節(jié),純粹是為了占位標識對象存在。

結(jié)果:

我們可以看到結(jié)果確實是正確的。

this指針

Date類中有 Init 與 Print 兩個成員函數(shù),函數(shù)體中沒有關(guān)于不同對象的區(qū)分,那當d1調(diào)?Init和Print函數(shù)時,該函數(shù)是如何知道應(yīng)該訪問的是d1對象還是d2對象呢?那么這?就要看到C++給了?個隱含的this指針解決這?的問題 a編譯器編譯后,類的成員函數(shù)默認都會在形參第?個位置,增加?個當前類類型的指針,叫做this指針。?如Date類的Init的真實原型為,void Init(Date* const this, int year,int month, int day)類的成員函數(shù)中訪問成員變量,本質(zhì)都是通過this指針訪問的,如Init函數(shù)中給_year賦值,this->_year = year;C++規(guī)定不能在實參和形參的位置顯?的寫this指針(編譯時編譯器會處理),但是可以在函數(shù)體內(nèi)顯?使?this指針。

在類里還有一個隱藏的this指針。

#include

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->_year

_year = year;

_month = month;

_day = day;

}

//void Print(Date* const this)

void Print()

{

//cout << this->_year << "/" << this->_month << "/" << this->_day << endl;

cout << _year << "/" << _month << "/" << _day << endl;

}

private:

// 聲明

int _year;

int _month;

int _day;

};

int main()

{

// Date類實例化出對象d1和d2

Date d1;

Date d2;

//d1.Init(&d1, 2024, 8, 6);

//d2.Init(&d2, 2025, 8, 7);

d1.Init(2024, 8, 6);

d2.Init(2025, 8, 7);

//d1.Print(&d1);

//d2.Print(&d2);

d1.Print();

d2.Print();

return 0;

}

當我們傳參數(shù)給成員函數(shù)的時候,還隱藏傳著實例化的地址,

當然C++規(guī)定不能在實參和形參的位置顯?的寫this指針(編譯時編譯器會處理)。

我們可以看到這個,this接收實例化后的地址,,但是這個const修飾地址不能改變,但是可以修改。

當成員函數(shù)在使用的時候,lnit在訪問成員變量的時候,不是year = year這樣的,而是this->year = year這樣的,

傳過來的是實例化的地址,通過實例化地址來訪問成員變量,進行賦值,

Print那個打印函數(shù)也是一樣的,通過實例化地址進行打印。

下?通過兩個選擇題測試?下前?的知識學得如何?

1.下?程序編譯運?結(jié)果是()

A、編譯報錯 B、運?崩潰 C、正常運?

#include

using namespace std;

class A

{

public:

void Print()//this接收了p,但是p是空指針

{

//但是這里沒有對空指針進行訪問,所以不會報錯

//這里只是打印

cout << "A::Print()" << endl;

}

private:

int _a;

};

int main()

{

A* p = nullptr;//初始化為空

p->Print();//這里相當于把p的地址傳過去,這里雖然寫了p->,但是沒有解引用

return 0;

}

分析:成員函數(shù)在編譯時確定的,沒有存在對象中,所以這里雖然寫了p->,但是沒有解引用。

所以選擇【C.正常運行】

2.下?程序編譯運?結(jié)果是()

A、編譯報錯??B、運?崩潰? C、正常運?

#include

using namespace std;

class A

{

public:

void Print()//this接收了p,p是空指針

{

cout << "A::Print()" << endl;

//這里this->_a對空指針進行解引用了

cout << _a << endl;

}

private:

int _a;

};

int main()

{

A* p = nullptr;//初始化為空

p->Print();//這里相當于把p的地址傳過去,這里雖然寫了p->,但是沒有解引用

return 0;

}

分析:成員函數(shù)這里,_a已經(jīng)對空指針解引用了,所以運行崩潰。

3. this指針存在內(nèi)存哪個區(qū)域的 ()

A. 棧??B.堆??C.靜態(tài)區(qū)??D.常量區(qū)??E.對象??

this是一個隱藏的形參,函數(shù)調(diào)用要建立棧,函數(shù)要存放在棧里,this是一個隱藏的形參,也是存放在棧里的。

在VS系列編譯器,this通過寄存器ecx傳遞。

C++和C語?實現(xiàn)Stack對?

?向?qū)ο笕?特性:封裝、繼承、多態(tài),下?的對?我們可以初步了解?下封裝。 通過下?兩份代碼對?,我們發(fā)現(xiàn)C++實現(xiàn)Stack形態(tài)上還是發(fā)?了挺多的變化,底層和邏輯上沒啥變 化。

C++中數(shù)據(jù)和函數(shù)都放到了類??,通過訪問限定符進?了限制,不能再隨意通過對象直接修改數(shù) 據(jù),這是C++封裝的?種體現(xiàn),這個是最重要的變化。這?的封裝的本質(zhì)是?種更嚴格規(guī)范的管 理,避免出現(xiàn)亂訪問修改的問題。當然封裝不僅僅是這樣的,我們后?還需要不斷的去學習。C++中有?些相對?便的語法,?如Init給的缺省參數(shù)會?便很多,成員函數(shù)每次不需要傳對象地 址,因為this指針隱含的傳遞了,?便了很多,使?類型不再需要typedef?類名就很?便在我們這個C++??階段實現(xiàn)的Stack看起來變了很多,但是實質(zhì)上變化不?。等著我們后?看STL 中的?適配器實現(xiàn)的Stack,?家再感受C++的魅?。

C實現(xiàn)Stack代碼

C語言的這個棧沒有封裝函數(shù),可以自己訪問到結(jié)構(gòu)體成員,進行修改。

這種情況很容易出現(xiàn)問題。

#include

#include

#include

#include

typedef int STDataType;

typedef struct Stack

{

STDataType* a;

int top;

int capacity;

}ST;

void STInit(ST* ps)

{

assert(ps);

ps->a = NULL;

ps->top = 0;

ps->capacity = 0;

}

void STDestroy(ST* ps)

{

assert(ps);

free(ps->a);

ps->a = NULL;

ps->top = ps->capacity = 0;

}

void STPush(ST* ps, STDataType x)

{

assert(ps);

// 滿了, 擴容

if (ps->top == ps->capacity)

{

int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;

STDataType* tmp = (STDataType*)realloc(ps->a, newcapacity *

sizeof(STDataType));

if (tmp == NULL)

{

perror("realloc fail");

return;

}

ps->a = tmp;

ps->capacity = newcapacity;

}

ps->a[ps->top] = x;

ps->top++;

}

bool STEmpty(ST* ps)

{

assert(ps);

return ps->top == 0;

}

void STPop(ST* ps)

{

assert(ps);

assert(!STEmpty(ps));

ps->top--;

}

STDataType STTop(ST* ps)

{

assert(ps);

assert(!STEmpty(ps));

return ps->a[ps->top - 1];

}

int STSize(ST* ps)

{

assert(ps);

return ps->top;

}

int main()

{

ST s;

STInit(&s);

STPush(&s, 1);

STPush(&s, 2);

STPush(&s, 3);

STPush(&s, 4);

while (!STEmpty(&s))

{

printf("%d\n", STTop(&s));

STPop(&s);

}

STDestroy(&s);

return 0;

}

C++實現(xiàn)Stack代碼

向C++這種可以把成員變量進行私有,不能外部進行修改訪問,只能通過公有成員函數(shù)進行訪問修改,這樣比較安全。

#include

#include

using namespace std;

typedef int STDataType;

class Stack

{

public:

// 成員函數(shù)

void Init(int n = 4)

{

_a = (STDataType*)malloc(sizeof(STDataType) * n);

if (nullptr == _a)

{

perror("malloc申請空間失敗");

return;

}

_capacity = n;

_top = 0;

}

void Push(STDataType x)

{

if (_top == _capacity)

{

int newcapacity = _capacity * 2;

STDataType* tmp = (STDataType*)realloc(_a, newcapacity *

sizeof(STDataType));

if (tmp == NULL)

{

perror("realloc fail");

return;

}

_a = tmp;

_capacity = newcapacity;

}

_a[_top++] = x;

}

void Pop()

{

assert(_top > 0);

--_top;

}

bool Empty()

{

return _top == 0;

}

int Top()

{

assert(_top > 0);

return _a[_top - 1];

}

void Destroy()

{

free(_a);

_a = nullptr;

_top = _capacity = 0;

}

private:

// 成員變量

STDataType* _a;

size_t _capacity;

size_t _top;

};

int main()

{

Stack s;

s.Init();

s.Push(1);

s.Push(2);

s.Push(3);

s.Push(4);

while (!s.Empty())

{

printf("%d\n", s.Top());

s.Pop();

}

s.Destroy();

return 0;

}

柚子快報激活碼778899分享:c語言 C++類和對象(上)

http://yzkb.51969.com/

相關(guān)閱讀

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19504591.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機訪問

文章目錄