(一一九)类作用域

简介:

变量、函数具有不同的作用域,C++的也引入了一种新的作用域:类作用域

 

在类中定义的名称(如类数据成员和类成员函数名)的作用域,都为整个类,作用域为整个类的名称,在该类之中是已知的,在类外是不可知的(如私有成员变量、公有成员变量和函数也算,因为需要使用作用域解析运算符才能调用)。

 

因此,可以在不同类中使用相同的类成员名而不会引起冲突(例如man类里有一个int a,而player类里也有一个int a,这2个是不会冲突的)。

 

在类声明或成员函数定义中,可以使用未修饰的成员名称(未限定的名称)。

 

以上大概意思就是,类里面的变量、函数名,可以随便起,只要别和同一个类里面的冲突就行(也不能起例如int int这样变量名),他和类外的名字是不会冲突的。

 

 

 

当常量的作用域为类时:

当需要在类中,声明一个数组时(例如是一个有4个元素的int数组),假如若需要给这个数组的成员个数,使用常量来代替。

 

一般在类外,我们是这样做的,首先,使用const int M=4; 这样创建一个常量M(其值为4),然后,使用int b[M]; 创建一个有4个元素的int数组b

 

但是,在类内,是不可以这么做的。

 

原因在于,声明一个类时,实际上是没有创建类对象,只是描述的对象的形式。只有在创建对象时,例如 man a; 时,调用默认构造函数,来创建一个类对象a。但在创建对象a之前,是没有用于存储其的空间的。

 

而函数不同,函数在创建时,是有其内存地址的(所以才有函数指针,指向某个函数)。因此函数内部创建一个常量,是有存储这个常量的空间的。

 

 

为了解决在类中创建一个符号常量的问题,有两个办法:

使用枚举。在类中声明一个枚举,然后给枚举的成员赋值。

声明枚举,例如:enum{M=4};

使用枚举,例如:int b[M];

综合起来:

enum { M = 4 };

int b[M];

之后,就可以用枚举变量M来代表常量4

 

使用没有链接性的静态常量。我们知道,静态常量的持续性是从声明时,一直到程序结束。因此,我们创建一个作用域为类的静态变量,就可以解决这个问题。

因为是只在类中起效,无需在文件中起效,所以创建方法类似在函数内部创建链接性为内部的静态变量,如:

static const int M = 10;

int b[M];

这个时候,M被保存在用于存储静态变量的内存之中(而不是存储在对象之中)。因此,int b[M]就可以调用静态常量M了。

 

 

 

 

作用域内枚举(C++11):

假如有两个枚举,他们都有一个叫做first的成员,如:

enum aa first ,secondthird };

enum bb { firstsecondthird };

这种情况下,编译器会提示这样声明是有错的。原因在于,他们有着同名的枚举成员(共3个),发生了名称冲突的问题。

 

而类可以解决这个问题,C++11提供了一种新枚举,其枚举量的作用域为类,声明方法如下:

enum class aa{first ,second,third}; //这是一种新枚举,枚举的作用域为类。

 

这种作用域为类的枚举,具有很多特点,如代码:

#include<iostream>
#include<string>

int main()
{
	using namespace std;
	enum class aa{first ,second,third};	//这是一种新枚举,枚举的作用域为类。
	enum bb { first, second, third };

	aa q = aa::first;	//需要用作用域解析运算符
	bb w = second;
	
	//int e = q; //这样的代码是不支持的
	
	int r = w;
	if (r < third)	//r和third是作用域不是类的枚举bb的成员
		cout << "1" << endl;
	
	//if (r<aa::third)	//这个也是不行的

	//if (r < q)cout << "2" << endl;	//这个也是不行的

	if (r<int(aa::third))	//只有被显式转换后——int(aa:third) ,才能用作一个整型
		cout << "2" << endl;

	system("pause");
	return 0;
}

总结:

①声明时,需要在enum和枚举名前,加入class,如:

enum class aa{first ,second,third};

 

②在使用这个作用域为类的枚举时,需要使用作用域解析运算符,如:

aa::first

但这种用法,不能直接将其赋值给一个int值,例如:int q=aa::first这样是不可以的。只能赋给类型为这种枚举名的变量,例如:

aa q = aa::first;

 

③若要使用这种枚举成员,不能像普通枚举那样,直接引用变量名,而是需要通过显式类型转换才能够使用,如:

int(aa::third)

 

 

另注:书中注明C++11作用域内枚举的底层类型可以被修改,如默认为int类型,使用enum class : short pizza { small,large };可以修改常规枚举的底层类型。

但我个人使用的Visual Studio 2015,是无法实现的,不知为何。


目录
相关文章
|
存储 编译器 程序员
【C++】类与对象(一)类的定义 访问限定符 类的实例化 this指针
【C++】类与对象(一)类的定义 访问限定符 类的实例化 this指针
|
1月前
|
自然语言处理 JavaScript 前端开发
词法作用域和静态作用域有什么区别
【10月更文挑战第12天】词法作用域和静态作用域有什么区别
|
2月前
|
Java
作用域
作用域
19 2
|
2月前
C 作用域详解
在 C 语言中,作用域决定了变量和函数的可见性和生命周期,包括块作用域、函数作用域、文件作用域和全局作用域。块作用域内的变量仅在块内有效,函数作用域内的变量在整个函数内有效,文件作用域内的全局变量和函数在整个文件内有效,而全局作用域内的变量和函数在整个程序运行期间有效。作用域的优先级遵循局部变量优先的原则,局部变量会遮蔽同名的全局变量。变量的生命周期分为局部变量(函数调用时创建和销毁)、全局变量(程序开始时创建和结束时销毁)以及静态变量(整个程序期间有效)。理解作用域有助于避免命名冲突和错误,提高代码的可读性和可维护性。
|
6月前
|
JavaScript 前端开发 Python
函数与作用域
编程中的函数与作用域概念。函数是可重用的代码块,能提高代码的可读性、可维护性和复用性。基础用法包括定义、调用和返回值。高级用法涉及函数嵌套、匿名函数(lambda函数)和装饰器。装饰器能在不修改原函数代码的情况下添加功能。 作用域决定了变量的可见范围,从内到外是局部、嵌套、全局和内置作用域。闭包是能访问外部函数变量的内部函数,即使外部函数执行完毕,闭包仍能保留其状态。闭包常用于实现特殊功能,如记忆化和延迟执行。 立即执行函数表达式(IIFE)是JavaScript中的模式,用于创建私有作用域和防止变量污染全局。IIFE常用于封装变量、避免命名冲突以及实现模块化和函数作为参数传递。
|
6月前
|
JavaScript 前端开发 Java
什么是作用域,它的作用是什么?
什么是作用域,它的作用是什么?
171 1
|
6月前
|
存储 C语言 C++
【c++】类和对象 - 类的访问限定符及封装/作用域和实例化
【c++】类和对象 - 类的访问限定符及封装/作用域和实例化
【c++】类和对象 - 类的访问限定符及封装/作用域和实例化
|
存储 安全 编译器
【C++基础】类与对象(上):访问限定符、类作用域、类实例化、类对象模型、this指针
【C++基础】类与对象(上):访问限定符、类作用域、类实例化、类对象模型、this指针
123 0
|
Linux 网络架构
暂时性死区以及函数作用域
暂时性死区以及函数作用域
175 0
|
存储 编译器 程序员
【C++要笑着学】类和对象 | 初识封装 | 访问限定符 | 类的作用域和实例化 | 类对象模型 | this指针(二)
本章将正式开始学习C++中的面向对象,本篇博客涵盖讲解 访问限定符、封装的基础知识、类的作用域和实例化、探究类对象的存储和对于this指针由浅入深地讲解。
167 0
【C++要笑着学】类和对象 | 初识封装 | 访问限定符 | 类的作用域和实例化 | 类对象模型 | this指针(二)