C++之静态函数用法及说明

 更新时间:2026年05月23日 10:30:39   作者:IOT-Power  
title:理解静态函数的使用场景和规则description:本文详细解释了静态函数的概念及其使用场景,包括全局初始化、释放资源和工具函数等-3个对象,重点在于于处理整个类而非单个对象的操作,通过具体例子帮助读者更好地理解和应用,静的成员函数的使用场景和编写方式

类中的静态函数,就是属于“类本身”的函数,不属于某一个具体对象。

最典型的写法是:

class ZlogBase
{
public:
    static void Initialize(const std::string& config_path);
    static void Shutdown();
};

这两个函数前面有 static,它们就是静态成员函数。

一、怎么使用

静态函数最常见的调用方式是:

ZlogBase::Initialize("log.conf");
ZlogBase::Shutdown();

也就是:

类名::函数名()

因为它属于类本身,所以不需要先创建对象。

对比一下普通成员函数

普通成员函数:

class ZlogBase
{
public:
    void logInfo(const char* msg) const;
};

这种函数必须通过对象调用:

ZlogBase logger("tcpserver");
logger.logInfo("server start");

不能直接:

ZlogBase::logInfo("server start");   // 错

因为 logInfo() 需要依赖某个对象内部的数据,比如:

  • m_pZlogCategory
  • this

二、为什么静态函数可以直接用类名调用

因为静态函数没有 this 指针

普通成员函数在内部其实默认都带着一个隐藏参数:

this

表示“当前对象是谁”。

比如:

logger.logInfo("hello");

本质上像是:

logger.logInfo(&logger, "hello");

只是这个 this 是编译器自动传进去的。

但是静态函数没有 this,所以它不能访问对象成员变量,也不依赖某个对象。
既然它不依赖对象,那就可以直接:

ZlogBase::Initialize(...)

三、静态函数里能做什么,不能做什么

能做的

可以做和“整个类”有关、但和“某个具体对象”无关的事情。

例如:

  • 全局初始化
  • 全局释放
  • 计数器
  • 工具函数
  • 工厂函数
  • 单例访问入口

不能直接做的

不能直接访问普通成员变量,比如:

class ZlogBase
{
protected:
    zlog_category_t* m_pZlogCategory = nullptr;

public:
    static void Initialize(const std::string& config_path);
};

Initialize() 里不能直接写:

m_pZlogCategory = ...;   // 错

因为 m_pZlogCategory 属于某个对象,
而静态函数不知道你想操作哪个对象。

四、为什么Initialize()适合做成静态函数

你现在这个例子最典型:

ZlogBase::Initialize(LOG_FILE_PATH);

因为“初始化日志系统”这件事,本质上是整个程序级别的事情,不是某一个 TcpServer 或某一个 System 对象自己的事情。

它通常做的是:

zlog_init(LOG_FILE_PATH);

这是全局初始化。

所以它很适合写成:

static void Initialize(...);

这样你在 main() 里程序启动时就能先调用:

ZlogBase::Initialize(LOG_FILE_PATH);

后面再去创建:

  • System
  • TcpServer
  • DevInfo

这些对象。

五、为什么要“先 Initialize,再创建对象”

因为很多对象在构造时就要用日志。

比如:

class TcpServer : public ZlogBase
{
public:
    TcpServer() : ZlogBase("tcpserver") {}
};

ZlogBase("tcpserver") 里面可能会调用:

zlog_get_category("tcpserver");

那前提就是:

zlog 系统已经先初始化好了。

所以顺序必须是:

ZlogBase::Initialize(...);   // 先初始化整个日志系统
TcpServer server;            // 再创建具体对象

这就是为什么 Initialize() 设计成静态函数,并且在 main() 里直接调用最合理。

六、一个非常好理解的类比

比如学校系统:

class Student
{
public:
    static void SetSchoolName(const std::string& name);
    void SetStudentName(const std::string& name);
};

学校名称

这是所有学生共享的,属于“整个类”的事情,所以适合静态函数:

Student::SetSchoolName("No.1 Middle School");

学生姓名

这是某个具体学生自己的事情,所以必须通过对象:

Student s;
s.SetStudentName("Tom");
  • ZlogBase::Initialize() 就像“设置学校名字”,是全局动作。
  • logInfo() 就像“设置学生名字”,是对象动作。

七、静态函数常见使用场景

在实际项目里,静态函数常见于这几类:

1. 全局初始化 / 释放

像你这个:

ZlogBase::Initialize(...);
ZlogBase::Shutdown();

2. 计数器

class Test
{
public:
    static int Count();
};

统计一共创建了多少对象之类。

3. 工具函数

class Math
{
public:
    static int Add(int a, int b);
};

直接:

Math::Add(1, 2);

不需要先创建 Math 对象。

4. 单例入口

class Config
{
public:
    static Config& instance();
};

八、静态函数和静态成员变量经常配合使用

例如:

class ZlogBase
{
public:
    static void Initialize(const std::string& path);

private:
    static bool s_inited;
};

这里:

  • Initialize() 是静态函数
  • s_inited 是静态变量

这两个都属于类本身,而不是某个对象。

所以非常适合做“全局只初始化一次”的逻辑。

九、你现在这个例子应该怎么理解

你截图里的:

QCoreApplication a(argc, argv);
ZlogBase::Initialize(LOG_FILE_PATH);

System* pApp = new System();
pApp->Init();

应该理解成:

第一步

程序启动,先初始化日志系统:

ZlogBase::Initialize(LOG_FILE_PATH);

第二步

再创建系统对象:

System* pApp = new System();

如果 System 继承了 ZlogBase,那它在构造时就能安全使用日志功能。

十、一句话总结

静态函数用于处理“属于整个类、而不属于某个具体对象”的事情。

所以像:

  • 初始化日志系统
  • 关闭日志系统

这种全局动作,最适合写成:

ZlogBase::Initialize(...);
ZlogBase::Shutdown();

而像:

  • logInfo()
  • logError()

这种依赖对象内部状态的函数,就必须通过对象调用。

如果你愿意,我下一条可以继续专门讲一下:

静态成员变量和静态成员函数的关系,以及它们在 .h / .cpp 里应该怎么写。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 深入解析C++中的构造函数和析构函数

    深入解析C++中的构造函数和析构函数

    析构函数:在撤销对象占用的内存之前,进行一些操作的函数。析构函数不能被重载,只能有一个
    2013-09-09
  • C++11之强类型枚举的实现示例

    C++11之强类型枚举的实现示例

    本文主要介绍了C++11中引入的强制类型枚举来解决传统C风格枚举存在的命名泄漏、类型不安全和底层类型不确定三大问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-02-02
  • C++基础学生管理系统

    C++基础学生管理系统

    这篇文章主要介绍了C++基础学生管理系统的相关资料,包括了文件处理代码,链表处理代码,以及自定义代码,主函数自定义,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-04-04
  • 深入了解C++智能指针的使用

    深入了解C++智能指针的使用

    智能指针的本质就是使用一个对象来接管一段开辟的空间,在该对象在销毁的时候,自动调用析构函数来释放这段内存。本文就来和大家详细聊聊智能指针的使用,需要的可以参考一下
    2022-10-10
  • 详解Matlab绘制3D玫瑰花的方法(内附旋转版本)

    详解Matlab绘制3D玫瑰花的方法(内附旋转版本)

    这篇文章主要为大家介绍了如何利用Matlab绘制3D版的玫瑰花以及旋转版的3D玫瑰花,文中的示例代码讲解详细,感兴趣的小伙伴可以动手试一试
    2022-03-03
  • Qt中Tab与Tree组件实现分页菜单

    Qt中Tab与Tree组件实现分页菜单

    本文主要介绍tabWidget选择夹组件与TreeWidget树形选择组件的常用方法及灵活运用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-12-12
  • Qt实现电子时钟

    Qt实现电子时钟

    这篇文章主要为大家详细介绍了Qt实现电子时钟,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-06-06
  • 循环队列详解及队列的顺序表示和实现

    循环队列详解及队列的顺序表示和实现

    这篇文章主要介绍了循环队列详解及队列的顺序表示和实现的相关资料,需要的朋友可以参考下
    2016-12-12
  • C++中this指针用法示例详解

    C++中this指针用法示例详解

    在C++编程中this指针是每个非静态成员函数的隐含参数,指向调用对象的地址,它用于区分同一个类的不同实例,并访问成员变量和成员函数,这篇文章主要介绍了C++中this指针用法的相关资料,需要的朋友可以参考下
    2024-09-09
  • C++实践排序函数模板项目的参考方法

    C++实践排序函数模板项目的参考方法

    今天小编就为大家分享一篇关于C++实践排序函数模板项目的参考方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-02-02

最新评论