首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

枚举类型的使用解决方案

2012-03-15 
枚举类型的使用class RuntimeStringCmp{public:enum cmp_mode{normal, nocase}cmp_mode modepublic:Runt

枚举类型的使用
class RuntimeStringCmp
{
public:
enum cmp_mode{normal, nocase};
cmp_mode mode;
public:
RuntimeStringCmp(cmp_mode m=normal):mode(m){}


构造函数中,为什么可以直接使用normal啊??? RuntimeStringCmp(cmp_mode m=normal):mode(m){}


normal是属于类的啊


 



[解决办法]
很多人没有回答在点子上,

作为c++标准控,我用c++标准回答你,你给出的例子只是一个特例,下面是一个更复杂的例子,

class RuntimeStringCmp
{
public:
enum cmp_mode{normal, nocase};
cmp_mode mode;
public:
RuntimeStringCmp(cmp_mode m=normal);
};

RuntimeStringCmp::RuntimeStringCmp(cmp_mode m) : mode(m) {
mode = normal;
mode = nocase;
}

//注意,contructor定义这里可以写成
RuntimeStringCmp::RuntimeStringCmp(RuntimeStringCmp::cmp_mode m) : mode(m) {
RuntimeStringCmp::mode = RuntimeStringCmp::cmp_mode::normal;
RuntimeStringCmp::mode = RuntimeStringCmp::cmp_mode::nocase;
}

你应该问的问题是,在
RuntimeStringCmp::RuntimeStringCmp(cmp_mode m) : mode(m) {
mode = normal;
mode = nocase;
}
中,为什么cmp_mode不需要前面加上RuntimeStringCmp::,
为什么mode不需要加上 RuntimeStringCmp::,
为什么normal和nocase不需要加上RuntimeStringCmp::,或者为什么不是RuntimeStringCmp::cmp_mode::normal和RuntimeStringCmp::cmp_mode::nocase?

这个和作用域以及name lookup相关,答案如下,根据c++11标准,

1. 首先,unscoped enum里面的每一个enumerator的定义域并不是{和}之间,而是声明enum的作用域,即enum里面的每一个enumerator都相当于声明在enum外面。

enum color { red, blue };
color a = red; //ok, red相当于声明在{}外面,和color同一个作用域
color b = color::blue; //ok too

所以,用enumerator red或者blue的时候,前面的color::可以省略。

2. 再回来看你的问题,


class RuntimeStringCmp
{
public:
enum cmp_mode{normal, nocase};
cmp_mode mode;
public:
RuntimeStringCmp(cmp_mode m=normal);
};

你问的问题是,为什么normal不是RuntimeStringCmp::normal(从前面我们也可以看出,也可以写成RuntimeStringCmp::cmp_mode::normal),你还需要问一个问题,就是为什么cmp_mode不是RuntimeStringCmp::cmp_mode。

其实C++中,为了书写方便,定义了一系列及其复杂的名字寻找方法,对于cmp_mode或者normal来讲,重要的不是要写全称(RuntimeStringCmp::cmp_mode),重要的是编译器能不能正确寻找到这个名字真正代表了什么东西。如果找不到,ok,你必须写全称,如果能找到,你就可以省略全称。

让我们来看一下C++标准中怎样寻找一个类中的名字,例如cmp_mode或者normal。

简单的说,C++规定,如果在类的定义中用到一个没有加::的名字(unqualified name),例如,
public:
RuntimeStringCmp(cmp_mode m=normal);
这个声明是在类定义中的,所以这里的cmp_mode和normal都是类定义中名字,这种名字编译器需要从这个类中寻找,如果找不到,会从这个类的基类中寻找,如果找不到,会从类定义之前的namespace寻找,这个例子中就会从global namespace中寻找。

所以cmp_mode和normal的写法没有问题。

3. 我们回头看这个contructor的定义,

RuntimeStringCmp::RuntimeStringCmp(cmp_mode m) : mode(m) {
mode = normal;
mode = nocase;
}

对于这
{
mode = normal;
mode = nocase;
}
里面的名字(A name used in the definition of a member function),
C++规定,
先从 {
}里面找,找不到,就从类定义找,类定义也找不到,就从基类找,也找不到,才从上一层namespace找。

4. 对于
RuntimeStringCmp::RuntimeStringCmp(cmp_mode m) : mode(m) {
mode = normal;
mode = nocase;
}

中的
RuntimeStringCmp::RuntimeStringCmp(cmp_mode m) : mode(m)

里的名字,C++规定,

如果声明或者定义一个函数的时候,如果该函数是一个qualified id,即被::限制住的名字,上例中的RuntimeStringCmp::RuntimeStringCmp(注意这个不单单对class适用,对namespace也适用),在这个函数名字之后的所有的名字(一直到函数定义{}之前),都可以从该函数的类或者namespace来寻找。即上例中的cmp_mode和mode,都可以从RuntimeStringCmp这个类中寻找。

注意------------------------- 这个规则并不适用于RuntimeStringCmp::RuntimeStringCmp之前的名字。举例说明,

class RuntimeStringCmp
{
public:
enum cmp_mode{normal, nocase};
cmp_mode mode;
public:
RuntimeStringCmp(cmp_mode m=normal);
//下面是正确的,因为2个cmp_mode都是在类定义中,名字从该类中寻找
cmp_mode example_function(cmp_mode m);
};

下面是错误的,因为第一个cmp_mode找不到!第二个cmp_mode可以找到,因为是在 RuntimeStringCmp::example_function后面。
cmp_mode RuntimeStringCmp::example_function(cmp_mode m) {
}

必须写成,
RuntimeStringCmp::cmp_mode RuntimeStringCmp::example_function(cmp_mode m) {
}

恩。希望楼主你能明白。

热点排行