c++ - 自己实现一个nullptr
PHP中文网
PHP中文网 2017-04-17 15:36:51
0
1
425
const class nullptr_t
{
public:
    template<class T>
    inline operator T*() const
        { return 0; }

    template<class C, class T>
    inline operator T C::*() const
        { return 0; }
 
private:
    void operator&() const;
} nullptr = {};

来自维基的代码,但是看不懂,求大佬解释。

PHP中文网
PHP中文网

认证0级讲师

全部回覆(1)
巴扎黑

根據你的描述,在vs2013寫瞭如下程式碼,示範。

//nullptr.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;
const class mynullptr_t
{
public:
    template<class T>
    inline operator T*() const
    {
        cout << "T* is called" << endl;
        return 0;
    }
    template<class C, class T>
    inline operator T C::*() const
    {
        cout << "T C::* is called" << endl;
        return 0;
    }

private:
    void operator&() const;
    
} mynullptr = {};

class A{
public:
      int *a;
};

int main(){

    int *p = mynullptr;
    int A::*a = mynullptr;
    cout << p << endl;
    cout << a << endl;

}

結果輸出
T* is called
T C::* is called
00000000
0

解釋:
首先申明了一個類別(為了避免衝突我使用了mynullptr_t)使用了const修飾,表示裡面的變數是不能更改的。
同時類別裡面有兩個公有函數

template<class T>
operator T*() const;
template<class C, class T>
operator T C::*() const

其中template表示模板,意味著,T可以使用戶自訂的類型。既然是空指針,那麼很多種類型的指針都可以指向它,所以使用了模板。使用了operator關鍵字,所以此函數為一個隱式轉換函數。 const表示此函數不修改類別的成員變數。如果對這方面不是很清楚可以參考
1.c++模板詳解 2.C++ operator兩種用法這兩篇部落格。
在函數裡面只做了一件事也就是回傳0,為什麼回傳0呢?因為在指標賦值時如果指標=0,也即表示這個指標為一個空指標。原因是因為在頭檔下有以下定義:

/* Define NULL pointer value */
#ifndef NULL
#ifdef __cplusplus
#define NULL    0
#else  /* __cplusplus */
#define NULL    ((void *)0)
#endif  /* __cplusplus */
#endif  /* NULL */

將NULL 定義為了0;
不信的話可以試試看

int *p = 0;
cout << p << endl;

輸出:00000000

第二個函數跟上面的一樣只是模板不同

template<class C, class T>
    operator T C::*() const
    {
        cout << "C::T* is called" << endl;
        return 0;
    }

目的是為了給類別的成員指標變數賦予空指標。所以你可以根據你自己的需求寫出各種模板參數。
private中void operator&() const;即為將&符號停用。
在main函數中分別定義了一下變數

int *p = mynullptr;
int A::*c = mynullptr;

int *的指針p並賦予空指針,和並對類A 的成員指針賦予空指針。
要把mynullptr賦給左邊的值,所以說此時要進行隱式類型轉化,如何轉化呢。還記得我們在類別中寫的那兩個函數嗎,他們就是隱式轉換的函數。根據左邊的類型去匹配模板,第一個當然與T*匹配,所以呼叫第一個隱式轉換函數,於是結果印了T* is called。同樣的第二個應該呼叫第二個隱式轉換函數,印了C::T* is called。我們知道空指標的位址為0位址,所以第一個印了00000000(32位元系統指標佔4個位元組,所以是8個0)。第二個由於是成員指針,代表的是偏移量,由於是空指針所以是0。

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板