c++头文件预处理对于 static静态全局变量和静态全局函数的影响


前言

c++头文件预处理对于 static静态全局变量和静态全局函数的影响


我们经常会碰到以下几个问题:
(1)不要在头文件中声明static的全局变量?
(2)不要在头文件中声明static的全局函数?
为什么呢?
static的变量核心作用有两个:
一、多个对象间共享数据:static变量理论上应该只有一份,未初始化时存在BSS区,初始化之后存储在数据段区。在类文件中定义static的全局变量,其核心作用也是为了实现类的多个对象之间的数据共享。
二、不破坏类的封装性:相对于全局变量,static可以在实现类的多个对象之间数据共享的前提下,不破坏类的封装性。
其中问题(1)、问题(2),违背了第一条,我们接下来详细说明。

一、不要在头文件中声明static的全局变量

1.先上对应的错误代码示例

//声明static的全局静态变量头文件
//CommonStaticTest.h
static int static_int_test = 10;   //"static全局静态变量"错误定义位置示例
class CommonStaticTest
{
	public:
		CommonStaticTest();
		~CommonStaticTest();
}

//引用头文件“CommonStaticTest.h”类1
//UseCommonStaticTestClass1.cpp
#include "CommonStaticTest.h"
UseCommonStaticTestClass1::UseCommonStaticTestClass1()
{
}
UseCommonStaticTestClass1::~UseCommonStaticTestClass1()
{
}
void UseCommonStaticTestClass1::Fun_Use_Static_Test()
{
	cout<<"UseCommonStaticTestClass1 static_int_test address"<<&static_int_test<<endl; //打印当前的全局静态变量地址
}

//引用头文件“CommonStaticTest.h”类2
//UseCommonStaticTestClass2.cpp
#include "CommonStaticTest.h"
UseCommonStaticTestClass2::UseCommonStaticTestClass2()
{
}
UseCommonStaticTestClass2::~UseCommonStaticTestClass2()
{
}
void UseCommonStaticTestClass2::Fun_Use_Static_Test()
{
	cout<<"UseCommonStaticTestClass2 static_int_test address"<<&static_int_test<<endl; //打印当前的全局静态变量地址
}

//主函数
#include "UseCommonStaticTestClass1.h"
#include "UseCommonStaticTestClass2.h"
void main()
{
	UseCommonStaticTestClass1 m_UseCommonStaticTestClass1;
	UseCommonStaticTestClass2 m_UseCommonStaticTestClass2;
	getchar();
	reture 0;
}

2.运行结果

运行上述代码,我们能够获得输出结果:

UseCommonStaticTestClass1 static_int_test address = 0099F3F8
UseCommonStaticTestClass2 static_int_test address = 0099F3FC

其中主类"CommonStaticTest.h"将静态全局变量"static_int_test"定义在头文件中,而测试类"UseCommonStaticTestClass1.cpp"与"UseCommonStaticTestClass2.cpp"分别在其源文件中引入了主类的头文件"CommonStaticTest.h",看现象静态变量被"static_int_test"重复定义了多次。
进而导致该静态变量并没有起到一个在类的多个对象之间实现资源共享的作用。

3.原因分析

这里我们借助c++预处理的过程来解释一下:
首先注意预处理两点内容:
(1)预处理在cpp文件中遇到#include<> 或者 #include " ",会将其替换对应头文件的内容。
(2)预处理在在它对应的源文件中有效。
我们将"UseCommonStaticTestClass1.cpp"与"UseCommonStaticTestClass2.cpp"分别预处理之后,变为:

//UseCommonStaticTestClass1.i
static int static_int_test = 10; //预处理替换头文件
UseCommonStaticTestClass1::UseCommonStaticTestClass1()
{
}
UseCommonStaticTestClass1::~UseCommonStaticTestClass1()
{
}
void UseCommonStaticTestClass1::Fun_Use_Static_Test()
{
	cout<<&static_int_test<<endl;
}

//UseCommonStaticTestClass2.i
static int static_int_test = 10; //预处理替换头文件
UseCommonStaticTestClass2::UseCommonStaticTestClass2()
{
}
UseCommonStaticTestClass2::~UseCommonStaticTestClass2()
{
}
void UseCommonStaticTestClass2::Fun_Use_Static_Test()
{
	cout<<&static_int_test<<endl;
}

这样我们就发现static 变量"static_int_test"分别在UseCommonStaticTestClass1.i与UseCommonStaticTestClass2.i文件中各自定义了一次。而静态变量的作用仅仅局限于定义它的源文件中,和其他源文件无关。进而就导致哪个源文件直接引用了定义全局静态变量的头文件,这个全局静态变量就会被重新再定义一次。这个静态全局变量也就失去了静态"共享"的作用。

二、不要在头文件中声明static的全局函数

1.同样也是先上错误的代码示例

//声明static的全局静态函数头文件
//CommonStaticTest.h
static void static_Fun_test(){return;}   //"static全局静态函数"错误定义位置示例
class CommonStaticTest
{
	public:
		CommonStaticTest();
		~CommonStaticTest();
}

//引用头文件“CommonStaticTest.h”类1
//UseCommonStaticTestClass1.cpp
#include "CommonStaticTest.h"
UseCommonStaticTestClass1::UseCommonStaticTestClass1()
{
}
UseCommonStaticTestClass1::~UseCommonStaticTestClass1()
{
}
void UseCommonStaticTestClass1::Fun_Use_Static_Test()
{
	cout<<"UseCommonStaticTestClass1 static_Fun_test address"<<&static_Fun_test<<endl; //打印全局静态函数入口地址
}

//引用头文件“CommonStaticTest.h”类2
//UseCommonStaticTestClass2.cpp
#include "CommonStaticTest.h"
UseCommonStaticTestClass2::UseCommonStaticTestClass2()
{
}
UseCommonStaticTestClass2::~UseCommonStaticTestClass2()
{
}
void UseCommonStaticTestClass2::Fun_Use_Static_Test()
{
	cout<<"UseCommonStaticTestClass2 static_Fun_test address"<<&static_Fun_test<<endl; //打印全局静态函数入口地址
}

//主函数
#include "UseCommonStaticTestClass1.h"
#include "UseCommonStaticTestClass2.h"
void main()
{
	UseCommonStaticTestClass1 m_UseCommonStaticTestClass1;
	UseCommonStaticTestClass2 m_UseCommonStaticTestClass2;
	getchar();
	reture 0;
}

2.运行结果

运行上述代码,我们能够获得输出结果:

UseCommonStaticTestClass1 static_Fun_test address = 0099F3F8
UseCommonStaticTestClass2 static_Fun_test address = 0099F3FC

其中主类"CommonStaticTest.h"将静态全局函数"static_Fun_test"定义在头文件中,而测试类"UseCommonStaticTestClass1.cpp"与"UseCommonStaticTestClass2.cpp"分别在其源文件中引入了主类的头文件"CommonStaticTest.h",看现象同样发现静态全局函数"static_Fun_test"同样被重复定义了多次。
进而导致该静态全局函数并没有起到一个在类的多个对象之间实现共享的作用。

3.原因分析

其错误原因与问题(1)相同,不再重复说明。

总结

限于本人水平,如果本文说明和代码有表述不当之处,还请指出。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值