<C++学习>C++ 静态函数

📅 发布时间:2026/7/4 23:22:14 👁️ 浏览次数:
<C++学习>C++ 静态函数
类中的静态函数就是属于“类本身”的函数不属于某一个具体对象。最典型的写法是classZlogBase{public:staticvoidInitialize(conststd::stringconfig_path);staticvoidShutdown();};这两个函数前面有static它们就是静态成员函数。一、怎么使用静态函数最常见的调用方式是ZlogBase::Initialize(log.conf);ZlogBase::Shutdown();也就是类名::函数名()因为它属于类本身所以不需要先创建对象。对比一下普通成员函数普通成员函数classZlogBase{public:voidlogInfo(constchar*msg)const;};这种函数必须通过对象调用ZlogBaselogger(tcpserver);logger.logInfo(server start);不能直接ZlogBase::logInfo(server start);// 错因为logInfo()需要依赖某个对象内部的数据比如m_pZlogCategorythis二、为什么静态函数可以直接用类名调用因为静态函数没有this指针。普通成员函数在内部其实默认都带着一个隐藏参数this表示“当前对象是谁”。比如logger.logInfo(hello);本质上像是logger.logInfo(logger,hello);只是这个this是编译器自动传进去的。但是静态函数没有this所以它不能访问对象成员变量也不依赖某个对象。既然它不依赖对象那就可以直接ZlogBase::Initialize(...)三、静态函数里能做什么不能做什么能做的可以做和“整个类”有关、但和“某个具体对象”无关的事情。例如全局初始化全局释放计数器工具函数工厂函数单例访问入口不能直接做的不能直接访问普通成员变量比如classZlogBase{protected:zlog_category_t*m_pZlogCategorynullptr;public:staticvoidInitialize(conststd::stringconfig_path);};在Initialize()里不能直接写m_pZlogCategory...;// 错因为m_pZlogCategory属于某个对象而静态函数不知道你想操作哪个对象。四、为什么Initialize()适合做成静态函数你现在这个例子最典型ZlogBase::Initialize(LOG_FILE_PATH);因为“初始化日志系统”这件事本质上是整个程序级别的事情不是某一个TcpServer或某一个System对象自己的事情。它通常做的是zlog_init(LOG_FILE_PATH);这是全局初始化。所以它很适合写成staticvoidInitialize(...);这样你在main()里程序启动时就能先调用ZlogBase::Initialize(LOG_FILE_PATH);后面再去创建SystemTcpServerDevInfo这些对象。五、为什么要“先 Initialize再创建对象”因为很多对象在构造时就要用日志。比如classTcpServer:publicZlogBase{public:TcpServer():ZlogBase(tcpserver){}};而ZlogBase(tcpserver)里面可能会调用zlog_get_category(tcpserver);那前提就是zlog 系统已经先初始化好了。所以顺序必须是ZlogBase::Initialize(...);// 先初始化整个日志系统TcpServer server;// 再创建具体对象这就是为什么Initialize()设计成静态函数并且在main()里直接调用最合理。六、一个非常好理解的类比比如学校系统classStudent{public:staticvoidSetSchoolName(conststd::stringname);voidSetStudentName(conststd::stringname);};学校名称这是所有学生共享的属于“整个类”的事情所以适合静态函数Student::SetSchoolName(No.1 Middle School);学生姓名这是某个具体学生自己的事情所以必须通过对象Student s;s.SetStudentName(Tom);ZlogBase::Initialize()就像“设置学校名字”是全局动作。logInfo()就像“设置学生名字”是对象动作。七、静态函数常见使用场景在实际项目里静态函数常见于这几类1. 全局初始化 / 释放像你这个ZlogBase::Initialize(...);ZlogBase::Shutdown();2. 计数器classTest{public:staticintCount();};统计一共创建了多少对象之类。3. 工具函数classMath{public:staticintAdd(inta,intb);};直接Math::Add(1,2);不需要先创建Math对象。4. 单例入口classConfig{public:staticConfiginstance();};八、静态函数和静态成员变量经常配合使用例如classZlogBase{public:staticvoidInitialize(conststd::stringpath);private:staticbools_inited;};这里Initialize()是静态函数s_inited是静态变量这两个都属于类本身而不是某个对象。所以非常适合做“全局只初始化一次”的逻辑。九、你现在这个例子应该怎么理解你截图里的QCoreApplicationa(argc,argv);ZlogBase::Initialize(LOG_FILE_PATH);System*pAppnewSystem();pApp-Init();应该理解成第一步程序启动先初始化日志系统ZlogBase::Initialize(LOG_FILE_PATH);第二步再创建系统对象System*pAppnewSystem();如果System继承了ZlogBase那它在构造时就能安全使用日志功能。十、一句话总结静态函数用于处理“属于整个类、而不属于某个具体对象”的事情。所以像初始化日志系统关闭日志系统这种全局动作最适合写成ZlogBase::Initialize(...);ZlogBase::Shutdown();而像logInfo()logError()这种依赖对象内部状态的函数就必须通过对象调用。如果你愿意我下一条可以继续专门讲一下静态成员变量和静态成员函数的关系以及它们在.h/.cpp里应该怎么写。