• 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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    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;
    }
    
    • 1
    • 2
    • 3
    • 4

    命名空间之间的互相嵌套

    namespace wl
    {
    	int a;
    	namespace wl1
    	{
    		int a;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    编译器会把命名空间合并

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

    文件域

    • 一般变量默认都为extern
    • const 修饰的变量只能在本文件中使用,而要想在其它文件中使用,则必须显示的加上extern
    • static修饰的变量,只能在本文件中使用(符号表中被修饰成了 “l” (local))
  • 相关阅读:
    字节5年测试工程师经验分享,软件测试真的很简单么?
    论文笔记:Skeleton Key: Image Captioning by Skeleton-Attribute Decomposition
    深入理解 Swift Combine
    安卓gradle使用
    12.数据结构之梯度下降查找抛物线的极值
    iOS开发之自定义的framework添加第三方framework,lipo和ar命令看.o文件
    深耕5G,芯讯通持续推动5G应用百花齐放
    1、40个linux高效运维命令总结
    LINUX 服务器中病毒了,后来追踪到的一个机器运行脚本,研究了一下对于初学者shell的人有很大的帮助
    什么是回流和重绘?
  • 原文地址:https://blog.csdn.net/aoeaoao/article/details/124553197