static关键字的含义:静态的。
static变量与static函数的内存分布: 待续(挖坑于2017/1/3)
其作用有:
case 1: 隐藏当前模块(cpp文件)的被static修饰的变量或函数.
case 2: 被static修饰的变量和函数可定义在h文件中,这样以来任何包含了该h文件的cpp文件都相当于定义了一个该函数或者变量,但是各个cpp文件中的变量或者函数只是名字相同却又是相互独立的.
所谓相互独立也就是说: 比如你在一个h文件中通过static定义了一个变量,然后在一个包含了该h文件的cpp文件中修改了该变量,但是在别的cpp文件中访问的时候访问到的还是初始值并没有被修改.
//test.h
#include <iostream>
struct Test {
static int sNum;
};
//int Test::sNum = 10; //error! 如果在这里定义会报错说多重定义了.
static int x = 0;
static void testHeadFunctionS(const int& number)
{
std::cout << number << std::endl;
}
extern int y; //定义在其他cpp文件中.
extern void testCpp(); //同上.
extern void useTestClassInTestCpp();
//下面的 变量 和 函数 是错误的不能定义在被多次包含的h文件中.
/*
int m = 0;
void testHeadFunction()
{
std::cout << "the function defined in head file" << std::endl;
}
*/
//test.cpp
#include "test.h"
int Test::sNum = 100;
static int z = 20; //只能在该 cpp文件被使用.
static void testCppStatic() //只能在该cpp文件被使用.
{
++x; //注意这里我们使用了test.h文件中的 static int x = 20;
std::cout << "test cpp static" << std::endl;
}
int y = 20; //定义了声明在test.h文件中的 extern int y;
void testCpp() //定义了声明在test.h文件中的 extern void testCpp();
{
std::cout << "test cpp file" << std::endl;
std::cout << "static value x In test.cpp :" << x << std::endl;
std::cout << "static value x address In test.cpp :" << &x << std::endl;
std::cout << std::endl;
testHeadFunctionS(20);
testCppStatic();
}
void useTestClassInTestCpp()
{
Test testCpp{};
std::cout << "the address In test.cpp :" << &Test::sNum << std::endl;
std::cout << "the address In test.cpp :" << &testCpp.sNum << std::endl;
++Test::sNum;
std::cout << "the value In test.cpp :" << Test::sNum << std::endl;
std::cout << "the value In test.cpp :" << testCpp.sNum << std::endl;
}
//source.cpp
#include "test.h"
int main()
{
testHeadFunctionS(10);
testCpp();
std::cout << y << std::endl;
std::cout << std::endl;
std::cout << "static value x In main.cpp :" << x << std::endl;
std::cout << "static value x address In main.cpp :" << &x << std::endl;
std::cout << "--------------------------------------------" << std::endl;
Test main{};
std::cout << "sNum in main.cpp's address : " << std::endl;
std::cout <<"the address In main.cpp :" << &main.sNum << std::endl;
std::cout <<"the address In main.cpp :" << &Test::sNum << std::endl;
std::cout << "sNum in main.cpp :" << std::endl;
std::cout <<"the value In main.cpp :" << main.sNum << std::endl;
std::cout <<"the value In main.cpp :" << Test::sNum << std::endl;
std::cout << "--------------------------------------------" << std::endl;
useTestClassInTestCpp();
return 0;
}
运行截图:
case 3: 被static修饰的变量存放在静态数据区中,并且存在于整个程序的生命周期.
#include <iostream>
class Test {
public:
Test() = default;
~Test() { std::cout << "destroy" << std::endl; }
inline void print()const noexcept
{
std::cout << "<------------->" << std::endl;
}
};
void function()
{
std::cout << "shihuaMarryMe!!!!!!!!!" << std::endl;
static Test test_one; //注意这里! 当函数执行完毕后并没有执行test的析构函数.
Test test_two;
}
int main()
{
function(); //运行该函数我们发现 test_one的析构函数在下面的cout之前运行, test_two则是在之后.
std::cout << "--------------" << std::endl;
return 0;
}
case 4:对当前修饰的变量提供默认初始化(变量必须声明在函数内).
#include <iostream>
static char a1;
static int i1;
char x;
int y;
class Test {
public:
static char a;
int i;
Test() = default;
~Test() = default;
};
int main()
{
char a_;
int i_;
static char a; //提供默认初始化.
static int i; //提供默认初始化.
std::cout << a1 << " " << i1 << std::endl;
std::cout << a << " " << i << std::endl;
//std::cout << a_ << " " << i_ << std::endl; //error
std::cout << x << " " << y << std::endl; //ok.
//std::cout << Test::a << std::endl; //error.
//std::cout << Test::i << std::endl; //error.
return 0;
}
case 5: 声明类内静态成员函数和数据成员为静态.
但是有几点需要注意:
1, 类内静态成员函数不能使用this指针.
2,类内静态成员函数不能调用类内其他非static的函数和数据成员.
3,类内静态成员函数只能访问该类内静态成员函数和静态数据成员.
4,且静态成员函数不能是volatile, const, virtual的.
//header.h
#ifndef HEADER_H
#define HEADER_H
#include <iostream>
extern void printValue()noexcept;
struct Test{
//static int number1{10}; //case1: error!
//static int number1; //case2: error!
//static int number1 = 10; //case3 : error!
static int number1; //case4: error!
static const int number2{20};
constexpr static const int number3{30};
};
//int Test::number1{0}; //case2: error!
//int Test::number1 = 10; //case4: error!
#endif // HEADER_H
//header.cpp
#include <iostream>
#include "header.h"
int Test::number1{10};//或者: int Test::number1 = 10;
void printValue()noexcept
{
Test test;
std::cout << test.number1 << std::endl;
}
//main.cpp
#include <iostream>
#include "header.h"
int main()
{
printValue();
Test test;
std::cout << test.number1 << std::endl;
return 0;
}
看了这么多那么有没有办法在h文件中声明定义函数呢?
Demo1:
在Demo1的例子中我们提供了: test.h; test.cpp; source.cpp.其中如果test.h这个文件被包含了2次,因此当我们编译的时候就会报错,多重定义,编译器无法链接.
但是如果我们只包含一次test.h是没问题的,看下面的例子:
//test.h
#include <iostream>
int m = 0;
void testHeadFunction()
{
std::cout << "the function defined in head file" << std::endl;
}
#include "test.h"
int main()
{
testHeadFunction();
return 0;
}
Demo:
//head.h
#include <iostream>
extern int number;
//int num; //error!!!!!!!!
void function();
inline void functionInl()
{
std::cout << "inline function" << std::endl;
}
inline namespace TT {
inline void functionNpc()
{
std::cout << "namespace inline function!" << std::endl;
}
}
template<typename Ty>
void functionTem(Ty val)
{
std::cout << val << std::endl;
}
void functionUseTem();
//test1.cpp
#include "head.h"
template void functionTem<int>(int val);
void function()
{
functionTem<int>(20);
}
int number = 20;
//test2.cpp
#include "head.h"
extern template void functionTem<int>(int val);
void functionUseTem()
{
functionTem<int>(20);
}
//main.cpp
#include <iostream>
#include "head.h"
int main()
{
std::cout << number << std::endl;
function();
functionInl();
functionTem(20);
functionNpc();
functionUseTem();
return 0;
}