1. 程式人生 > 其它 >C++封裝 之 this指標

C++封裝 之 this指標

this指標

概念

  • this指標的作用:避免函式引數與資料成員重名
  • this指標就是指向物件自身資料的指標,代表物件本身的地址
  • 成員函式通過this指標訪問到對應的資料成員。
  • 編譯時,編譯器自動為每個引數列表都加了this指標,所以程式設計師可以省略引數列表中的this指標

例項

  • 定義一個Array類
  • 資料成員:m_iLen表示陣列長度
  • 成員函式:建構函式、解構函式、封裝函式、資訊輸出函式
demo1.cpp原始碼
#include<iostream>
#include<stdlib.h>
using namespace std;
/************************************************************
 * demo1.cpp 中類的資料成員(m_iLen)與成員函式的引數(len)不重名
 * *********************************************************/

class Array{
public:
    Array(int len);    //建構函式
    ~Array();          //解構函式
    void setLen(int x);
    int getLen();
    void printfInfo();
private:
    int m_iLen;
};

Array::Array(int len){
    m_iLen = len;
}

Array::~Array(){

}

void Array::setLen(int len){
    m_iLen = len;
}
int Array::getLen(){
    return m_iLen;
}
void Array::printfInfo(){
    cout << "m_iLen = " << m_iLen << endl;
}

/****************** 測試主函式 ******************************/
int main(){
    Array arr1(4);
    cout << arr1.getLen()<<endl;
    arr1.printfInfo();

    system("pause");
    return 0;
}
執行結果
 4
 m_iLen = 4
demo2.cpp原始碼
#include<iostream>
#include<stdlib.h>
using namespace std;
/************************************************************
 * demo2.cpp 中類的資料成員(Len)與成員函式的引數(len)重名 !!! 執行錯誤
 * *********************************************************/

class Array{
public:
    Array(int len);    //建構函式
    ~Array();          //解構函式
    void setLen(int x);
    int getLen();
    void printfInfo();
private:
    int len;      //資料成員(Len)與成員函式的引數(len)重名
};

Array::Array(int len){
    len = len;    //編譯器會疑惑是將引數賦值給資料成員,還是將資料成員賦值給引數
}

Array::~Array(){

}

void Array::setLen(int len){
    len = len;
}
int Array::getLen(){
    return len;
}
void Array::printfInfo(){
    cout << "len = " << len << endl;
}

/****************** 測試主函式 ******************************/
int main(){
    Array arr1(4);
    cout << arr1.getLen()<<endl;
    arr1.printfInfo();

    system("pause");
    return 0;
}

/*******************************
執行結果(錯誤):
4201131
len = 4201131
 *******************************/

執行結果(錯誤)
4201131
len = 4201131
demo3.cpp原始碼
#include<iostream>
#include<stdlib.h>
using namespace std;
/************************************************************
 * demo3.cpp 使用this指標解決資料成員(Len)與成員函式的引數(len)重名的問題,執行結果正確
 * *********************************************************/

class Array{
public:
    Array(int len);    //建構函式
    ~Array();          //解構函式
    void setLen(int x);
    int getLen();
    void printfInfo();
private:
    int len;      //資料成員(Len)與成員函式的引數(len)重名
};

Array::Array(int len){
    this->len = len;      // 新增this指標 ,編譯器不會再疑惑是將引數賦值給資料成員,還是將資料成員賦值給引數
}

Array::~Array(){

}

void Array::setLen(int len){
    this->len = len;      // 新增this指標
}
int Array::getLen(){
    return len;
}
void Array::printfInfo(){
    cout << "len = " << len << endl;
}

/****************** 測試主函式 ******************************/
int main(){
    Array arr1(4);
    cout << arr1.getLen()<<endl;
    arr1.printfInfo();

    system("pause");
    return 0;
}
執行結果(正確)
4
len = 4

this指標的特殊用法

修改函式printfInfo():
在函式printfInfo()的宣告和定義中,將返回型別改為Array,並在printfInfo()的定義中返回this指標 ,事實上返回型別後面需要加&或*,後面再講到。

int printfInfo(){
    cout << "len = " << m_iLen << endl;
}

修改為:

Array Array::printfInfo(){   // 修改printfInfo()函式的返回值為Array
    cout << "len = " << len << endl;
    return *this;            // 返回this指標
}

由於函式printfInfo()返回了this指標,所以理論上語句 arr1.printfInfo().setLen(8) 相當於arr1.setLen(8) ,也就是該語句修改資料成員len為8,測試主函式如下:

int main(){
    Array arr1(4);
    arr1.printfInfo().setLen(8);    //printfInfo()函式中返回了arr1物件的this指標,這裡相當於arr1.setLen(8)
    cout << arr1.getLen()<<endl;    //檢查上一條語句是否修改了資料成員len的值,執行結果發現len的值並沒有改變, 為什麼呢?
                                     
    return 0;
}
執行結果(len修改不成功):
len = 4
4
  • Q : 為什麼語句arr1.printfInfo().setLen(8)並沒有修改len的值?
  • A : 這是因為printfInfo()函式是Array型別的,返回的this指標指向了一個新的Array物件(一個臨時物件),而不是原來的物件arr1
  • Q : 如果希望printfInfo()返回的this指標指向arr1 ,該怎麼辦呢?
  • A : 在printfInfo()函式的返回型別後加引用,即Array& Array::printfInfo()

demo4.cpp原始碼
#include<iostream>
#include<stdlib.h>
using namespace std;
/************************************************************
 * demo4.cpp this指標的特殊用法,修改成員函式 printfInfo()的返回型別,返回this指標
 * *********************************************************/

class Array{
public:
    Array(int len);   
    ~Array();         
    void setLen(int x);
    int getLen();
    Array& printfInfo();  //修改printfInfo()函式的返回型別為Array,並加 &
private:
    int len;              //資料成員(Len)與成員函式的引數(len)重名
};

Array::Array(int len){
    this->len = len;      // this指標
}

Array::~Array(){

}

void Array::setLen(int len){
    this->len = len;      //this指標
}
int Array::getLen(){
    return len;
}
Array& Array::printfInfo(){  // 修改printfInfo()函式的返回值為Array,並加 &
    cout << "len = " << len << endl;
    return *this;            // 返回this指標
}

/****************** 測試主函式 ******************************/
int main(){
    Array arr1(4);
    arr1.printfInfo().setLen(8);    //修改資料成員len
    cout << arr1.getLen()<<endl;    //檢查上一條語句是否修改了資料成員len的值
                                     
    system("pause");
    return 0;
}

執行結果(len被成功修改):
len = 4
8

繼續修改函式setLen():
Array& Array::setLen(int len){
    this->len = len;      //this指標
    return *this;
}

測試主函式:

int main(){
    Array arr1(4);
    arr1.printfInfo().setLen(8).printfInfo();    //setLen()後面直接呼叫其他成員函式
    //cout << arr1.getLen()<<endl;    //不需要該語句了

    return 0;
}

執行結果:

len = 4
len = 8

把引用修改為指標

demo6.cpp原始碼
#include<iostream>
#include<stdlib.h>
using namespace std;
/************************************************************
 * demo6.cpp this指標的特殊用法   把引用修改為指標
 * *********************************************************/

class Array{
public:
    Array(int len);   
    ~Array();         
    Array* setLen(int x); //函式的返回型別為Array  ,並加指標
    int getLen();
    Array* printfInfo();  //函式的返回型別為Array  ,並加指標
private:
    int len;              //資料成員(Len)與成員函式的引數(len)重名
};

Array::Array(int len){
    this->len = len;      // this指標
}

Array::~Array(){

}

Array* Array::setLen(int len){ 
    this->len = len;           //this指標
    return this;               
}
int Array::getLen(){
    return len;
}
Array* Array::printfInfo(){  // 修改printfInfo()函式的返回值為Array,並加指標
    cout << "len = " << len << endl;
    return this;             // 返回this指標,這裡不需要星號了
}

/****************** 測試主函式 ******************************/
int main(){
    Array arr1(4);
    //arr1.printfInfo().setLen(8).printfInfo();  
    arr1.printfInfo()->setLen(8)->printfInfo();    //改成指標的呼叫方式
                                     
    system("pause");
    return 0;
}
執行結果
len = 4
len = 8