【c++】的作用域 (局部域,类域,名字命名空间,文件域)


c++支持四个域:局部域,类域,名字空间域,文件域

局部域

函数域
在这里插入图片描述
这两个a就处于不同的局部域中
局部块域
在这里插入图片描述
这两个b也处于不同的局部域中。

变量定义在局部域中时只在该域中可见,而且当变量出了该作用域,就会自动析构。

当定义在局部域中的变量被static修饰后,它也只在该域中可见,
当静态变量被初始化且初始化的值不是0时,它存放在 .data段。
当静态变量未被初始化或者初始化的值为0时,那么它存放在 .bss段。
且在整个程序运行过程中都存活,但只在该局部域中可见。

static修饰的变量只初始化一次。
在这里插入图片描述

类域

在这里插入图片描述
类中的成员属性和成员方法有public,protected,private三种访问限定符

当成员属性和方法是public时
则可以通过 对象.来访问
而当成员属性和方法是
静态
时,
则可以通过类名:: 来调用。

而当成员和方法是protected,private,
只有在类中或者类的其它方法中才能使用该属于或者方法。
当成员属性和方法是静态时,
则可以通过 类名::来调用。

当成员和方法是private时,
子类无法访问该成员和方法。

类修饰指针

由类限制修饰指向变量的指针

class B
{
public:
    B(int x =0):value(x),sum(x+1){}
	static  void funb()
	{
		cout << "funb" << endl;
	}
	
public:
	int value;
	char ch[3];
	int sum;
};
int main()
{
	int a;
	B b(1),b2(2);
	int* pa = new int(10);
	int B::* bp = nullptr;//bp 只能指向B内中为int的成员变量
	bp = &B::value;
	bp = &B::sum;
	cout << b.*bp << endl;
	cout << b2.*bp << endl;

	return 0;
}

bp只能指向B类被public修饰的且类型为int的成员变量

因为bp指向的是偏移量,所以初始化时初始化为0xffffffff
在这里插入图片描述
value在类中的偏移量为8,所以bp的值为8
在这里插入图片描述

由类修饰指向函数的指针

class B
{
public:
	B(int x =0):value(x),sum(x+1){}
	static  void funb()
	{
		cout << "funb" << endl;
	}
	void func()
	{

	}
public:
	 int value;
	 char ch[3];
	 int sum;
};
int main()
{
	B b;
	void(*p)() = nullptr;
	void(B:: *p2)() = nullptr;//只能指向B中返回值为void,参数为void(还必须由隐含的this指针) 的成员函数
	//p2 = &B::funb; funb为静态函数,参数列表中没有this指针,不能指向
	p2 =&B::func;
	p2();//调用的时候也不能这样直接调用,因为还需要一个this指针
	(b.*p2)();//而是需要这样调用
	return 0;
}

p2只能指向B中返回值为void,参数为void(还必须由隐含的this指针) 的成员函数

被类修饰的指向函数的指针初始化为0
在这里插入图片描述
这种指针指向的不是偏移量,而是具体的函数地址,因为在对于类说,函数只有一份
在这里插入图片描述

调用的方式
假如b为B类型的对象,则为(b.*p2)();

命名空间

背景:

约在20世纪70年代以前,编译器编译源代码产生目标文件时,符号名与相应的变量和函数的名字是一样的,比如一个汇编代码里面包含 了一个函数foo,那么汇编器将它编译成目标文件后,foo在目标文件中的相对应符号也是foo,当后来UNIX平台和c语言发明时,已经存在了相当多使用汇编编写的库和目标文件,这样的话,当c程序要使用这些库时,c语言不可使用这些库中定义的函数和变量的名字作为符号名,否则就会根现有的目标文件产生冲突,比如有个用汇编编写的库中定义了一个函数main,那么我们在c语言中就不可以再定义一个main函数或变量了,如果一个c语言的目标文件想要用到使用Fortan语言编写的目标文件,我们也要防止它们的名称冲突,
为了防止符号名冲突UNIX下的c语言规定c语言源代码文件中的所有全局变量函数经过编译之后,相对应的符号名前应加上下划线" _",而Fortran语言的源代码经过编译之后,所有符号名前应加上" _“,后面也应加上” _"。
但是这种方法还没有从根本上解决符号冲突的问题,比如当程序很大时,不同模块由不同的部门开发,它们之间还可能会产生命名冲突,所有就有了命名空间这个东西。

命名空间主要是解决全局名字空间污染的问题(程序中全局实体名与其它程序中的全局实体名字冲突)

最基本的命名空间

 namespace wl
{
	int a;
}

命名空间之间的互相嵌套

namespace wl
{
	int a;
	namespace wl1
	{
		int a;
	}
}

编译器会把命名空间合并

编译器会自动把命名空间合并;
在这里插入图片描述
在这里插入图片描述

文件域

  • 一般变量默认都为extern
  • const 修饰的变量只能在本文件中使用,而要想在其它文件中使用,则必须显示的加上extern
  • static修饰的变量,只能在本文件中使用(符号表中被修饰成了 “l” (local))
  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值