Effective C++: static

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;
}

 

转载于:https://my.oschina.net/SHIHUAMarryMe/blog/712619

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值