c++ primer plus笔记(7)存储持续性、作用域和链接性,命名空间

一、多文件单独编译:

头文件(.h)实现文件(.cpp)主程序(.cpp)

1>函数原型(而非定义)、函数模板原型声明

2>结构、类声明

3>内联函数

1>函数、函数模板实现

2>结构、类实现

主函数(main()等)

//使用以下写法防止重复include" "

#ifndef ..._H_   //...一般为头文件名的全大写,符号常量

#define ..._H_

...                     //头文件内容

#endif

//包含头文件以使用其中的资源

#include<.h>    //库文件使用<>

#include".h"      //用户自定义文件使用""

//包含头文件以使用其中的资源

#include<.h>    //库文件使用<>

#include".h"      //用户自定义文件使用""

//一般来说不必重复包含

二、各种变量及其存储持续性、作用域和链接性:

①自动变量:不使用关键字(除被废弃的register),在(包括主函数)代码块中定义
int main()
{
   int a;            //自动变量a
   register int b;   //寄存器变量b。C++11将register关键字完全废弃,目前相当于C++98的auto(而现有的auto被用于自动类型推断)
   {
       int a;        //代码块中的自动变量只在该块中可见,并优先与该块外的同名变量
   }
}

自动变量存储持续性为自动,作用域为局部,无链接性。

//自动变量使用栈(stack)中的内存。

②静态变量:

int a;              //作用域为全局,链接性为外部(所有文件都可以使用)
static int b;       //作用域为全局,链接性为内部(只有该文件可用)
int main()
{
   ...;
}
void funct()
{
   static int c;    //作用域为局部,没有链接性(只有该函数能够使用它)
}

//未被初始化的静态变量将被自动初始化为0;

//函数也可使用static声明在标头处,此时函数链接性为内部,只有该文件可以使用该函数;

//静态变量使用静态区的内存,其只能被初始化一次(包括循环或多次调用导致的重复初始化不会奏效),被初始化之后长期存在与静态区,每次调用继承上一次的值。

void funct()
{
   static int c = 0;
   c++;
}
//像这样的函数第一次被调用时c初始化为0,其后每次调用不再重复c的初始化,而是直接使用静态区中上次的值

三、符号常量及全局变量的跨文件使用

①主程序和实现文件使用头文件中定义的符号常量:

头文件(.h):

const int a=1;       //符号常量

实现文件(.cpp):

#include<iostream>
#include".h"
const int d = 1;     //定义在实现文件或主程序文件中的符号常量链接性为内部,只有该文件可以使用
...
std::cout<<a;        //符号常量只需要包含其所属头文件就可以直接使用

主程序(.cpp):

#include<iostream>
#include".h"
...
int main()
{
   ...;
   std::cout<<a;     //符号常量只需包含其所属头文件就可直接使用
}

//符号常量作为一种资源,其链接性实际上是内部的,通过包含头文件,使得每个实现文件都包含该资源。若要改变这种内部链接性为外部,则使用:

extern const int d = 1;   //extern声明的符号常量链接性为外部,这意味着不可以重复包含

//实现文件和主程序文件中的static和const声明,链接性虽然都为内部,作用域为局部,但仍有区别:

static int a = 1;   //a为静态变量
const int a = 1;    //a为符号常量

②实现文件使用主程序或其他实现文件中定义的全局变量:

主程序(.cpp):

int c = 1;
int main()
{
   ...;
   return 0;
}

实现文件(.cpp):

#include<iostream>
...
extern int c;
std::cout<<c;      //使用主程序或其他实现文件中定义的全局变量,必须使用extern声明写在标头处,接下来就可直接使用
void show_c()
{
   int c = 2;
   cout<<c;        //c = 2
   cout<<::c;      //::c = 1,函数内定义了与已被extern声明的全局变量同名的变量时,使用域运算符(::)区分
}

③主程序使用实现文件中定义的全局变量:

实现文件(.cpp):

int b = 1;

主程序(.cpp):

include<iostream>
...//extern int b;
int main()
{
   ...;
   extern int b;
   std::cout<<b;    //使用实现文件中定义的全局变量,必须使用extern声明,写在标头或主函数内皆可
}

四、命名空间:

①命名空间(namespace)的声明:

namespace NAME
{
   ...;
   ...;
}

//命名空间只能在函数外声明。

//命名空间可以嵌套。

②使命名空间中的名称可见:

1>using声明:

using std::cout;      //使用std中的cout

2>using编译指令:

using namespace std;  //使std中的所有名称都可见

//很明显,using声明对权限的控制更加精确,所以推荐使用using声明。

//二者的细微区别:

#include "stdafx.h"
#include<iostream>
using namespace std;

namespace n1
{
	int x = 1;
}
namespace n2
{
	int x = 2;
}

int main()
{	
	//
	using n2::x;           //using 声明使程序使用n2中的x,更接近声明的行为(不能与声明重复使用,优先级和声明一样)
	using namespace n1;    //该句不奏效,using编译使n1的内容可用,而不一定要使用(没有则自动寻找,有则以声明的优先)
	
	//
	cout << x << endl;
	{
		int x = 4;
		cout << x << "," << n1::x << "," << n2::x << endl;
	}
	cout << x << endl;

	//
	system("pause");
    return 0;
}

//using声明与声明行为更加接近,因此using声明与声明行为是互相冲突的:

using n2::x;
int x;       //不允许

③使用using向已有的命名空间中添加新名称:

namespace elements
{
	namespace fire
	{
		int flame;
	}
}
namespace myth
{
	using namespace elements;                    //向myth中添加elements 必须使用using
}

④复杂(嵌套)命名空间的别名:

#include "stdafx.h"
#include<iostream>

namespace elements
{
	namespace fire
	{
		int flame;
	}
}
namespace myth
{
	using namespace elements;                    //向myth中添加elements
}
int main()
{
	using std::cout;
	using std::cin;
	namespace MEF = myth::fire;                   //使用=起别名  MEF简化
	using MEF::flame;
	flame = 1;
	cout << flame;
    return 0;
}

//不同于命名空间的声明只能在函数外,命名空间创建别名可以在任何位置进行。

//使用别名可以简化对复杂(嵌套)命名空间中变量的调用;

⑤未命名的命名空间:

namespace
{
   int count;   //链接性为内部,using该名称后作用域为using的区域
}
//未命名的名称空间由于其内部变量性质与static类似,且作用域控制更加灵活,故可以成为static的替代品。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值