C++中空指针访问成员函数的实现

 更新时间:2026年02月03日 08:53:40   作者:挖矿大亨  
本文主要介绍了C++中空指针访问成员函数的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、核心结论先明确

空指针(nullptr/NULL)可以调用类的非静态成员函数,但有一个严格前提:
函数内部没有通过this指针访问任何非静态成员变量 / 调用依赖成员变量的函数。
一旦访问成员变量,就会触发 “空指针解引用”,程序直接崩溃(段错误)。

二、代码示例:空指针调用成员函数的两种情况

  1. 能正常调用的情况(函数内不访问成员变量)
#include <iostream>
using namespace std;

class Person {
public:
    int age; // 非静态成员变量

    // 情况1:成员函数仅打印固定内容,不访问任何成员变量
    void showHello() {
        cout << "Hello, this is a member function!" << endl;
    }

    // 情况2:静态成员函数(无this指针,和空指针无关)
    static void showStatic() {
        cout << "Hello, this is a static member function!" << endl;
    }
};

int main() {
    // 定义空指针
    Person* p = nullptr;

    // 1. 空指针调用不访问成员变量的非静态成员函数 → 正常执行
    p->showHello(); 

    // 2. 空指针调用静态成员函数 → 正常执行(静态函数无this)
    p->showStatic(); 
    // 更规范的写法:Person::showStatic(); (静态函数优先用类名调用)

    return 0;
}
  1. 调用后崩溃的情况(函数内访问成员变量)
#include <iostream>
using namespace std;

class Person {
public:
    int age;

    // 函数内访问成员变量(会通过this->age访问)
    void showAge() {
        cout << "Age: " << this->age << endl; // 等价于 cout << age;
    }
};

int main() {
    Person* p = nullptr;
    p->showAge(); // 运行崩溃!空指针解引用

    return 0;
}

崩溃原因:
调用p->showAge()时,编译器会把p(空指针)作为this指针传入函数,函数内this->age等价于(nullptr).age—— 对空指针解引用,触发内存访问错误(段错误)。

三、底层原因:成员函数的存储与 this 指针

要理解这个现象,必须回到 C++ 对象模型和this指针的本质:

  • 成员函数的存储:所有非静态成员函数都存储在代码段(全局共享),不属于任何对象,对象的内存中只存成员变量;
  • 调用成员函数的本质:p->func()的逻辑是:
  • 找到Person类的func函数在代码段的地址;
  • 把p的地址作为this指针传入func;

执行func的代码。

空指针调用的关键:

  • 如果func内不使用this指针(不访问成员变量),仅执行固定逻辑,那么即使this是空指针,也能正常执行(因为没解引用this);
  • 如果func内使用this指针(访问成员变量),就会对空指针解引用,触发崩溃。

四、易踩坑的细节补充

const 成员函数也不例外:
const成员函数只是把this限定为const Person const,但如果this是空指针,访问成员变量依然崩溃:

void showAge() const {
    cout << age << endl; // 崩溃!this是空指针,this->age非法
}

空指针调用虚函数的特殊情况:
虚函数调用依赖this指针指向的虚表指针(vptr),空指针没有 vptr,因此调用虚函数会直接崩溃(无论是否访问成员变量):

class Person {
public:
    virtual void showHello() { // 虚函数
        cout << "Hello" << endl;
    }
};

int main() {
    Person* p = nullptr;
    p->showHello(); // 直接崩溃!需要访问this->vptr
    return 0;
}

语法合法但逻辑非法:
空指针调用成员函数在语法上是允许的(编译器不报错),但逻辑上是错误的 —— 除非你明确知道函数内不访问成员变量,否则绝对不要这么写。

总结

空指针可以调用非静态、非虚、且不访问成员变量的成员函数(语法合法,运行不崩溃);
空指针调用访问成员变量的成员函数 / 虚函数会崩溃(本质是对空指针解引用);
核心原因:成员函数存在于代码段,调用仅需传入this指针;是否崩溃取决于是否使用this指针访问内存。
开发建议:永远不要用空指针调用成员函数!即使语法上能运行,也是不规范、易出错的写法,可在函数开头加assert(this != nullptr)做校验,提前暴露问题。

到此这篇关于C++中空指针访问成员函数的实现的文章就介绍到这了,更多相关C++ 空指针访问内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++求解二叉树的下一个结点问题

    C++求解二叉树的下一个结点问题

    本文将通过C++求解以下问题:给定一个二叉树其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。文中示例代码讲解详细,感兴趣的可以了解一下
    2022-04-04
  • C++中httplib的使用小结

    C++中httplib的使用小结

    本文主要介绍了C++中httplib的使用小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-05-05
  • C++超详细讲解运算符重载

    C++超详细讲解运算符重载

    本文包括了对C++类的6个默认成员函数中的赋值运算符重载和取地址和const对象取地址操作符的重载。运算符是程序中最最常见的操作,例如对于内置类型的赋值我们直接使用=赋值即可,因为这些编译器已经帮我们做好了,但是对象的赋值呢?能直接赋值吗
    2022-06-06
  • C语言数据结构与算法之图的遍历(二)

    C语言数据结构与算法之图的遍历(二)

    这篇文章主要是介绍了利用广度优先算法实现图的遍历,文中利用图文详细的介绍了实现步骤,对我们学习数据结构与算法有一定的帮助,需要的朋友可以参考一下
    2021-12-12
  • C语言详解冒泡排序实现

    C语言详解冒泡排序实现

    冒泡排序是一种简单的排序算法,它也是一种稳定排序算法。其实现原理是重复扫描待排序序列,并比较每一对相邻的元素,当该对元素顺序不正确时进行交换。一直重复这个过程,直到没有任何两个相邻元素可以交换,就表明完成了排序
    2022-04-04
  • C++程序中启动线程的方法

    C++程序中启动线程的方法

    这篇文章主要介绍了C++程序中启动线程的方法,作者针对C++11版本中的一些新特性进行了解说,需要的朋友可以参考下
    2015-07-07
  • 详解C语言解决经典问题之兔子产子

    详解C语言解决经典问题之兔子产子

    有一对兔子,从出生后的第 3 个月起每个月都生一对兔子。小兔子长到第 3 个月后每个月又生一对兔子,假设所有的兔子都不死,问 30 个月内每个月的兔子总数为多少?本文将用C语言解决这一经典问题,需要的可以参考一下
    2022-03-03
  • C语言如何利用异或进行两个值的交换详解

    C语言如何利用异或进行两个值的交换详解

    最近在工作中遇到了两个值交换的需求,发现自己对异或有些忘记,所以索性写出来,方便以后需要的时候参考学习,下面这篇文章主要给大家介绍了关于C语言如何利用异或进行两个值的交换的相关资料,需要的朋友可以参考下。
    2017-09-09
  • C++ 创建桌面快捷方式 开始菜单的实现代码

    C++ 创建桌面快捷方式 开始菜单的实现代码

    这篇文章介绍了C++ 创建桌面快捷方式,开始菜单的实现代码,需要的朋友可以参考一下
    2013-06-06
  • C++对string进行大小写转换操作方法

    C++对string进行大小写转换操作方法

    这篇文章主要介绍了C++对string进行大小写转换操作方法,本文通过两种方法结合实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2023-02-02

最新评论