C++函數指針+對象指針+this指針+指向類靜態和非靜態成員的指針

1、指向函數的指針

函數的代碼在內存中的首地址,是由函數名表示的,也就是說函數名等價於函數代碼首地址。因此,可以定義一個指向函數的指針,即函數指針。函數指針定義和賦值的語法如下,其中數據類型代表指向函數的返回類型,形參表為指向函數的形參表;賦值時必須保證指向的函數名和函數指針的返回類型和形參完全相同:

數據類型 (*函數指針名)(形參表);
函數指針名 = 函數名;

下面的例子定義瞭一個函數和一個函數指針,通過函數指針調用函數代碼:

/// 1、預先定義一個返回int類型的函數
int addOne(int x) {
    x = x + 1;
    return x;
}

/// 2、定義並賦值函數指針
int (*pointerAddOne)(int x);
pointerAddOne = addOne;

/// 3、使用函數指針和使用函數名的方式相同
data = pointerAddOne(data);

2、對象指針

顧名思義,對象指針表示指向對象的指針。對象名即對象的地址,所以可以將對象的地址賦值給同類型的指針,從而通過該指針使用此對象。

定義與使用對象指針包含4個步驟:

  • 定義XXX類型指針;
  • 定義XXX類型對象;
  • 將對象地址賦值給指針;
  • 使用“(*對象指針名).成員名”或者“對象指針名->成員名”的形式使用對象的成員;

下面的例子展示瞭對象指針的定義與使用:

Duck duck(666);
/// 定義並賦值對象指針
Duck *pointerDuck;
pointerDuck = &duck;
/// 對象指針采用兩種方式訪問對象的成員
printf("%d \n", (*pointerDuck).getAge());
printf("%d \n", pointerDuck->getAge());

3、this指針

C++中,類的每個對象的數據成員都需要單獨分配內存,但是類的所有對象的函數成員共享內存。this指針是對象的非靜態成員函數的隱含參數,不需要自己進行定義,this指針指向當前調用非靜態成員函數的對象。當類對象調用非靜態成員函數時,對象的地址作為this指針的值,進而非靜態成員函數通過this指向的地址,來訪問對象的數據成員(類的不同對象的數據成員存儲在不同的地址,this指針用於傳遞對象的地址)。

this指針訪問其指向的對象數據成員的語法為:

this->數據成員名

下面的例子中,Duck類的成員函數getAge需要訪問對象的數據成員duckAge,但是由於函數中已經存在同名的duckAge變量,所以需要通過this來訪問數據成員duckAge

class Duck{
public:
    Duck(int age) { duckAge = age; };
    int getAge() { 
        int duckAge = 3;
            /// 通過this訪問對象的數據成員duckAge,而不是局部變量duckAge
        return this->duckAge; 
    };
private:
    int duckAge;
};

4、指向類的非靜態成員的指針

首先,類的靜態成員和非靜態成員是不同的,靜態成員屬於類,而非靜態成員屬於對象。指向類的非靜態成員的指針,包含指向數據成員的指針和指向函數成員的指針。聲明時需要指明指針指向的“類名”和“類型”,類型表示數據成員或函數成員的數據類型:

類型 類名::*數據成員指針名;
類型 (類名::*函數成員指針名)(參數表);

下面定義的Duck類包含public成員:int類型數據成員duckWeight和int類型函數成員getAge()(指向非靜態成員的指針也必須遵守訪問權限,不能指向private成員)下面分別聲明指向二者的指針:

int Duck::*pointerDuckWeight;
int (Duck::*pointerGetAge)();

指向非靜態成員的數據指針和函數指針賦值語法為:

數據成員指針名 = &類名::數據成員名;
函數成員指針名 = &類名::函數成員名;
下面對兩個指針進行賦值:

pointerDuckWeight = &Duck::duckWeight;
pointerGetAge = &Duck::getAge;

上面進行的聲明和賦值都是針對類進行的,所以並沒有指向對象的成員地址。這裡涉及到類的定義過程,類定義時並沒有分配內存,而隻是確定各個數據成員所占內存大小和相對位置。所以,可以使用對象的起始地址加相對位置對數據成員進行訪問。非靜態數據成員指針訪問成員的語法有如下兩種方式:

對象名.*數據成員的指針名
對象指針名->*數據成員指針名

/// 調用例子
printf("%d \n", duck.*pointerDuckWeight);

函數成員並不針對每個對象都有一個副本,而是共享的。對象調用函數成員時需要通過this指針,非靜態成員函數指針的調用包含下面兩種語法:

(對象名.函數成員指針名)(實參表)
(對象指針名->*函數成員指針名 )(實參表)

/// 實際調用的例子
printf("%d \n", (duck.*pointerGetAge)());

5、指向類的靜態成員的指針

對於類的靜態數據成員和函數成員,由於其並不屬於具體的對象,所以隻需要普通的數據型指針和函數型指針即可。

下面定義的Duck類包含用static聲明的靜態數據成員和靜態函數成員:

class Duck{
public:
    static int getAge() { 
        return 666;
    };
    static int duckWeight;
};
int Duck::duckWeight = 333;

下面是指向類的靜態成員的數據型指針和函數型指針的定義和賦值過程:

int *pointerDuckWeight;
int (*pointerGetAge)();
/// 賦值語法:指針名=&類名:靜態成員名
pointerDuckWeight = &Duck::duckWeight;
pointerGetAge = &Duck::getAge;

調用指針的時候,隻需要遵守基本數據型指針和函數型指針的調用語法即可:

printf("%d \n", *pointerDuckWeight);
printf("%d \n", (*pointerGetAge)());

到此這篇關於C++函數指針+對象指針+this指針+指向類靜態和非靜態成員的指針的文章就介紹到這瞭,更多相關C++指針內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: