C++中this指針用法示例詳解
一、this指針
• Date類中有 Init 與 Print 兩個成員函數(shù),函數(shù)體中沒有關(guān)于不同對象的區(qū)分,那當(dāng)d1調(diào)用Init和 Print函數(shù)時,該函數(shù)是如何知道應(yīng)該訪問的是d1對象還是d2對象呢?那么這里就要看到C++給了一個隱含的this指針解決這里的問題
• 編譯器編譯后,類的成員函數(shù)默認(rèn)都會在形參第?個位置,增加?個當(dāng)前類類型的指針,叫做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指針。
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; };
運(yùn)行下面兩串代碼,會發(fā)現(xiàn)兩個代碼雖然只差了一行代碼,結(jié)果卻差別很大
#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; }
#include<iostream> using namespace std; class A { public: void Print() { cout << "A::Print()" << endl; cout << _a << endl; } private: int _a; }; int main() { A* p = nullptr; p->Print(); return 0; }
這里先說結(jié)果,第一串代碼能正常運(yùn)行,第二串代碼會運(yùn)行崩潰,第一串代碼在調(diào)用了p->Print時這個函數(shù),但是并沒有對p這個空指針進(jìn)行解引用,所以第一串代碼能夠正常運(yùn)行,而第二串代碼,再調(diào)用print函數(shù)之后,里面的_a實際是this->_a,對p進(jìn)行了解引用,而p是空指針,而對于空指針的訪問只有在運(yùn)行時才會發(fā)生,編譯器在編譯階段不會發(fā)現(xiàn),所以不會程序報錯,會在運(yùn)行時崩潰。
在C++中,this指針是一個隱含的指向當(dāng)前對象的指針,它不是由程序員分配的,而是編譯器自動創(chuàng)建并插入到每個成員函數(shù)的隱式參數(shù)列表中的,this指針位于函數(shù)調(diào)用幀的局部變量區(qū),通常稱為??臻g,用于存儲函數(shù)執(zhí)行時需要的臨時數(shù)據(jù)和指向自身對象的數(shù)據(jù),當(dāng)函數(shù)被調(diào)用時,this 指針會被初始化為指向調(diào)用它的對象實例,這對于訪問類的私有成員變量特別有,this 永遠(yuǎn)不會為空,除非是在靜態(tài)成員函數(shù)或者非成員函數(shù)中,這時沒有特定的對象關(guān)聯(lián)。
二、C++和C語言實現(xiàn)Stack對比
面向?qū)ο笕筇匦裕悍庋b、繼承、多態(tài),下面的對比我們可以初步了解?下封裝,通過下面兩份代碼對比,我們發(fā)現(xiàn)C++實現(xiàn)Stack形態(tài)上還是發(fā)生了挺多的變化,底層和邏輯上沒啥變 化。
C實現(xiàn)stack代碼
#include<stdio.h> #include<stdlib.h> #include<stdbool.h> #include<assert.h> 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代碼
#include<iostream> 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; }
• C++中數(shù)據(jù)和函數(shù)都放到了類里面,通過訪問限定符進(jìn)行了限制,不能再隨意通過對象直接修改數(shù)據(jù),這是C++封裝的一種體現(xiàn),這個是最重要的變化,這里的封裝的本質(zhì)是一種更嚴(yán)格規(guī)范的管 理,避免出現(xiàn)亂訪問修改的問題,當(dāng)然封裝不僅僅是這樣的,我們后面還需要不斷的去學(xué)習(xí)。
• C++中有一些相對方便的語法,比如 Init 給的缺省參數(shù)會方便很多,成員函數(shù)每次不需要傳對象地 址,因為this指針隱含的傳遞了,方便了很多,使用類型不再需要typedef用類名就很方便。
總結(jié)
到此這篇關(guān)于C++中this指針用法示例詳解的文章就介紹到這了,更多相關(guān)C++ this指針詳解內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解C++中String類模擬實現(xiàn)以及深拷貝淺拷貝
這篇文章主要介紹了詳解C++中String類模擬實現(xiàn)以及深拷貝淺拷貝的相關(guān)資料,希望通過本文能幫助到大家,讓大家實現(xiàn)這樣的方法,需要的朋友可以參考下2017-10-10Visual?Studio2022下Opencv的配置圖文教程
本文主要介紹了Visual?Studio2022下Opencv的配置圖文教程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07在Visual Studio Code中配置C++編譯環(huán)境的問題
關(guān)于Visual Studio Code對C++環(huán)境的配置方法應(yīng)該有好多種,我這里用到了其中的兩種,具體內(nèi)容詳情文中給大家詳細(xì)介紹,對Visual Studio Code配置C++編譯環(huán)境相關(guān)知識感興趣的朋友一起看看吧2021-07-07C語言數(shù)據(jù)結(jié)構(gòu)系列隊列篇
本章我們將學(xué)習(xí) "隊列" ,首先介紹隊列的概念和結(jié)構(gòu),然后我們將著重講解棧的實現(xiàn)。我們從零開始寫隊列的接口,并從零開始步步解讀。本章將繼續(xù)鞏固畫思路草圖的能力,只要思路草圖畫好了,就可以很輕松地將其轉(zhuǎn)換成代碼2022-02-02