变量、函数具有不同的作用域,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 ,second, third };
enum bb { first, second, third };
这种情况下,编译器会提示这样声明是有错的。原因在于,他们有着同名的枚举成员(共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,是无法实现的,不知为何。