搜索

首页  >  问答  >  正文

c++ - 自己实现一个nullptr

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中文网2772 天前387

全部回复(1)我来回复

  • 巴扎黑

    巴扎黑2017-04-17 15:38:51

    根据你的描述,在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<class T>表示模板,意味着,T可以使用户自定义的类型。既然是空指针,那么很多种类型的指针都可以指向它,所以使用了模板。使用了operator关键字,所以此函数为一个隐式转换函数。const表示此函数不修改类的成员变量。如果对这方面不是很清楚可以参考
    1.c++模板详解 2.C++ operator两种用法这两篇博客。
    在函数里面只做了一件事也就是返回0,为什么返回0呢?因为在对指针赋值时如果指针=0,也即意味着这个指针为一个空指针。原因是因为在<stdio.h>头文件下有以下定义:

    /* 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。

    回复
    0
  • 取消回复