static也是我们经常用到的关键字,关于static有很多用法,而且在面向过程和面向对象编程中,static有着不同的意义。之前总是记不住,于是,本人强迫症又发作了,一定要搞懂它!!!
一.面向过程编程中的static关键字
1.静态全局变量
// C++Test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
static int s_test;
int nons_test;
int _tmain(int argc, _TCHAR* argv[])
{
//静态全局变量默认初始化为0
cout<<"static :"<<s_test<<endl;
//非静态全局变量默认初始化也是0,但如果是局部非静态变量,在VS中直接报错,不能通过编译
cout<<"non-static: "<<nons_test<<endl;
system("pause");
return 0;
}
non-static: 0
请按任意键继续. . .
//StaticTest.h头文件中分别定义静态全局变量和普通全局变量
static int static_num = 20;
int nonstatic_num = 30;
// C++Test.cpp : 定义控制台应用程序的入口点。
//全局变量在头文件或者本文件中两者没有什么区别
#include "stdafx.h"
#include <iostream>
#include <string>
#include "StaticTest.h"
#include "StaticTest1.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
//如果静态变量在头文件中或者本文件中,可以访问静态全局变量
cout<<"static :"<<static_num<<endl;
//如果静态变量在头文件中或者本文件中,可以访问非静态全局变量
cout<<"non-static: "<<nonstatic_num<<endl;
system("pause");
return 0;
}
non-static: 30
请按任意键继续. . .
//.h文件
#ifndef __STATICTEST1_H_
#define __STATICTEST1_H_
#pragma once
class StaticTest1
{
public:
StaticTest1(void);
virtual ~StaticTest1(void);
};
#endif
//.cpp文件
#include "stdafx.h"
#include "StaticTest1.h"
//在.cpp文件中定义全局变量
static int static_test = 10;
int nonstatic_test = 20;
StaticTest1::StaticTest1(void)
{
}
StaticTest1::~StaticTest1(void)
{
}
// C++Test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include "StaticTest1.h"
using namespace std;
extern int nonstatic_test;
extern int static_test;
int _tmain(int argc, _TCHAR* argv[])
{
//如果静态变量在其他.cpp文件中,不可以访问静态全局变量,即使在本文件使用extern声明也不行
//cout<<"static :"<<static_test<<endl;
//如果静态变量在其他.cpp文件中,可以访问非静态全局变量,但是要在本文件使用extern声明
cout<<"non-static: "<<nonstatic_test<<endl;
system("pause");
return 0;
}
1>: fatal error LNK1120: 1 个无法解析的外部命令
2.静态局部变量
// C++Test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void TestFunc()
{
//定义一个静态局部变量,但是这个变量仅仅在第一次的时候初始化,再次调用时不会再初始化
static int static_num = 10;
//但是普通局部变量,每次都会初始化
int nonstatic_num = 10;
static_num++;
nonstatic_num++;
cout<<"non_static: "<<nonstatic_num<<" static :"<<static_num<<endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
//调用10次该函数
for(int i = 0; i < 10; i++)
TestFunc();
system("pause");
return 0;
}
结果:
non_static: 11 static :11
non_static: 11 static :12
non_static: 11 static :13
non_static: 11 static :14
non_static: 11 static :15
non_static: 11 static :16
non_static: 11 static :17
non_static: 11 static :18
non_static: 11 static :19
non_static: 11 static :20
请按任意键继续. . .
从上面的结果我们看出,函数被调用了10次,非静态变量每次都被初始化,因而结果没变。而静态变量却只被初始化了一次,因而每次结果都比上一次大1。
关于局部静态变量要注意的几点:
1)局部静态变量也在全局数据区分配内存,不会因为函数调用结束而销毁。
2)局部静态变量在首次调用到该变量的时候进行初始化,之后再次调用时不会再进行初始化。并且局部静态变量一般就在声明处初始化,如果未显示初始化,则默认初始化为0
3)局部静态变量的生命周期为声明时到程序结束,但是它的作用域却是局部的,仅仅在该函数内,不会破坏局部性原理。
3.静态函数
//StaticTest.h
#include <iostream>
using namespace std;
void NormalFuncTest();
static void StaticFuncTest();
//StaticTest.cpp
#include "stdafx.h"
#include "StaticTest.h"
void NormalFuncTest()
{
cout<<"Normal Func!"<<endl;
}
static void StaticFuncTest()
{
cout<<"Static Func!"<<endl;
}
// C++Test.cpp : 定义控制台应用程序的入口点。
//main函数
#include "stdafx.h"
#include <iostream>
#include "StaticTest.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
NormalFuncTest();
StaticFuncTest();
system("pause");
return 0;
}
这个例子中有两个函数,都定义在另一个文件中,一个为普通函数,另一个为static函数。编译一下,会出现如下错误:\vs2012\vs12\vc\include\xlocnum(155): error C2129: 静态函数“void StaticFuncTest(void)”已声明但未定义
二.面向对象编程中的Static关键字
1.静态数据成员
// C++Test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
class StaticTest
{
private:
//此处为声明,声明一个静态成员变量
static int count;
int id;
public:
StaticTest(int i): id(i)
{
count++;
}
void Show()
{
cout<<"ID: "<<id<<endl;
}
static void ShowCount()
{
cout<<"Count: "<<count<<endl;
}
};
//在类外定义并初始化静态成员变量,由于定义时需要分配空间,所以不能在类声明中定义
int StaticTest::count = 0;
int _tmain(int argc, _TCHAR* argv[])
{
StaticTest test1(1);
StaticTest test2(2);
test1.Show();
test2.Show();
StaticTest::ShowCount();
system("pause");
return 0;
}
结果:
ID: 2
Count: 2
请按任意键继续. . .
2.静态成员函数
还是上面的那个例子,加了一部分功能:
// C++Test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
class StaticTest
{
private:
//此处为声明,声明一个静态成员变量
static int count;
int id;
public:
StaticTest(int i): id(i)
{
count++;
}
void Show()
{
//但是非静态成员函数可以访问静态成员函数和变量
cout<<"ID: "<<id<<" Count: "<<count<<endl;
}
static void ShowCount()
{
//静态成员函数不能访问非静态的成员,非静态成员函数也不行!
//cout<<"ID: "<<id<<endl; error C2597: 对非静态成员“StaticTest::id”的非法引用
//Show();: error C2352: “StaticTest::Show”: 非静态成员函数的非法调用
cout<<"Count: "<<count<<endl;
}
};
//在类外定义并初始化静态成员变量,由于定义时需要分配空间,所以不能在类声明中定义
int StaticTest::count = 0;
int _tmain(int argc, _TCHAR* argv[])
{
StaticTest test1(1);
StaticTest test2(2);
test1.Show();
test2.Show();
StaticTest::ShowCount();
system("pause");
return 0;
}
结果:
ID: 1 Count: 2
ID: 2 Count: 2
Count: 2
请按任意键继续. . .
关于静态成员函数注意的地方:
1)静态成员函数可以访问静态成员函数和静态成员变量。但是静态成员函数不能访问普通成员变量和普通成员函数。(因为静态成员函数没有this指针,属于共用)
2)非静态成员函数可以访问静态成员变量和静态成员函数。
3)定义在类外的静态成员函数不能加static,声明时加个static即可,定义时和普通成员函数相同。
4)静态成员函数与静态成员变量的调用规则一致,都不需要有对象就能调用。可以使用正常方法,也可以使用类名::调用。