1)以下代码显示了枚举元素星期三的索引。我怎样才能让它打印值而不是索引。
int main()
{
enum day{sunday,monday,tuesday,wednesday,thursday,friday,saturday};
day d=wednesday;
cout<<d;
return 0;
}
2)在什么情况下我会更喜欢匿名枚举而不是枚举
1)以下代码显示了枚举元素星期三的索引。我怎样才能让它打印值而不是索引。
int main()
{
enum day{sunday,monday,tuesday,wednesday,thursday,friday,saturday};
day d=wednesday;
cout<<d;
return 0;
}
2)在什么情况下我会更喜欢匿名枚举而不是枚举
1)。您的代码打印枚举的值,而不是索引。在您的具体示例中,索引与值相同(默认情况下,枚举的第一个值获取数值 0,其余获取连续增加的值。
去检查:
int main()
{
enum day{sunday = 5,monday,tuesday,wednesday,thursday,friday,saturday};
day d=wednesday;
cout<<d; // will print 8 (as in 5 + 1 + 1 + 1)
return 0;
}
如果“打印值”是指打印“星期三”,您应该这样做:
enum day{sunday,monday,tuesday,wednesday,thursday,friday,saturday};
std::ostream& operator << (std::ostream& out, const day d)
{
static const char *as_strings[] = {"sunday", "monday",
"tuesday", "wednesday", "thursday", "friday", "saturday"
};
return out << as_strings[static_cast<int>(d)]; // this only works
// for enum values starting from 0 and being consecutive
// otherwise you should use a switch(d) and
// print each value separately
}
int main()
{
day d=wednesday;
cout<<d; // will print wednesday
return 0;
}
编辑:
2)在什么情况下我会更喜欢匿名枚举而不是枚举
当您不需要将匿名枚举作为参数传递但需要为常量数值分配有意义的名称时,您更喜欢匿名枚举:
my_object record_to_myobject(record& r)
{
enum {id, value1, value2}; // indexes within record
int result_id = r[id]; // much more meaningful than r[0]
int result_value1 = r[value1];
int result_value2 = r[value2];
return my_object{result_id, result_value1, result_value2};
}
在这里使用匿名枚举很好,因为当您将值作为参数传递时,您需要一个 int,而不是枚举类型。如果你需要一个枚举类型,那么你必须给它一个名字。否则,你不会。
首先,该语言不提供将内部枚举值映射到字符串的任何方法。它不能,真的;考虑:
enum Numbers {
one = 1,
two = 2,
three = 3,
un = 1,
deux = 2,
trois = 3
};
将枚举常量分配给枚举变量后,它包含数值,仅此而已。而如果上面的数值是2,系统怎么知道应该映射到two
还是映射到deux
。
实际上,映射在许多情况下都很有用。很久以前,我写了一个简单的解析器来生成映射代码;它忽略了大多数 C++,在枚举被封装在宏中的情况下不起作用,如果枚举是私有的或受保护的,它生成的代码将无法编译,并且在上述情况下你得到的字符串是未定义的,但我仍然发现它非常有用。
对于第二个问题:当枚举的唯一目的是生成常量时,通常使用匿名枚举。像:
enum { maxSize = 4096 };
在您可以为静态成员变量提供初始化常量之前被广泛使用。而且我经常发现使用匿名枚举定义位掩码很方便,即使实际值是某种无符号类型。像:
enum {
offsetMask = 0xF000,
offsetShift = 12,
NS = 0x100,
CWR = 0x80,
ECE = 0x40,
URG = 0x20,
ACK = 0x10,
// ...
};
uint16_t flags;
// ...
flags = offset << offsetShift | ACK;
我不想声明我的变量有一个枚举;它们必须正好是 16 位(根据 TCP 规范)。在 C 语言中,我可能会使用 a #define
,而在现代 C++ 中,我可能会使用static uint16_t const
成员变量,但在我的 C++ 职业生涯的大部分时间里,像上面这样的东西本来是正常的解决方案。
您必须手动维护枚举值的字符串“描述”数组,这既乏味又容易出错:
static const char *daydescs[] = {
"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"
};
int main()
{
enum day{sunday,monday,tuesday,wednesday,thursday,friday,saturday};
day d=wednesday;
cout<< daydescs[(unsigned)d];
return 0;
}
枚举是一个数字,字符串表示(例如星期三)是编译时表示。
你需要类似的东西:
const char *dayname[] = {"sunday","monday","tuesday","wednesday","thursday","friday","saturday"};
...
cout << dayname[(unsigned)d];
...
试试下面的代码:
int main()
{
enum day{sunday,monday,tuesday,wednesday,thursday,friday,saturday};
String days[7] = {"sunday","monday","tuesday","wednesday","thursday","friday","saturday"};
day d=wednesday;
cout<<days[d];
return 0;
}
1)如果你只想要整数值,你可以写一个operator <<
重载:
template<typename _stream>
_stream& operator << (const day& value) {
_stream << static_cast<int>(value);
return _stream;
}
此外,请考虑使用枚举类而不是普通枚举(当然,如果您被允许使用 C++11)。
2)我会说可能有 1 种这样的情况:命名空间常量,假设你有一个Person
类并且想要有一些类内常量,比如MaxAge
or MaxNameLength
。但即使在这种情况下,将限制包装在类似的东西enum class Settings
中通常也是值得的。
此主题的类型安全变体是使用enum class
并将其用作std::map
#include <string>
#include <map>
#include <iostream>
int main()
{
enum class day
{
sunday,
monday,
tuesday,
wednesday,
thursday,
friday,
saturday
};
std::map<day,std::string> days =
{
std::make_pair(day::sunday, "Sunday"),
std::make_pair(day::monday, "Monday"),
std::make_pair(day::tuesday, "Tuesday"),
std::make_pair(day::wednesday, "Wednesday"),
std::make_pair(day::thursday, "Thursday"),
std::make_pair(day::friday, "Friday"),
std::make_pair(day::saturday, "Saturday")
};
std::cout << days[day::sunday] << std::endl;
}
这意味着使用整数类型访问映射将导致编译时错误。