如何解决使用static_cast
我一直在对函数输入参数使用枚举,但是我注意到这可能非常危险。
例如:
enum class MYENUM {
X1 = 0,X2
};
std::map<MYENUM,int> mymap;
//init mymap here with known enum values of X1 and X2
int MyFunc(const MYENUM& input) {
return mymap.at(input);
}
int main() {
MyFunc(static_cast<MYENUM>(10000));
}
因此10000
不是有效的enum
值。您将如何亲自找到解决方案?您是否将map
访问权限包含在try
块中,并将catch
包含在exception
中?如果我有许多函数可以使用用户输入的枚举值访问容器信息,怎么办?那么您也将try catch
放在所有这些函数中吗?
解决方法
您将如何亲自找到解决方案?
容易。引入类枚举的原因之一是类型安全-它们不会自动接受 any 值。所以,这里的代码
MyFunc(static_cast<MYENUM>(10000));
只是规避了语言所提供的安全性。解决方案很简单-请勿通过强制转换来绕过安全性,并且编译器不允许使用不正确的值。
如果其他人使用演员表-这不是您的问题。有人可以通过多种方式绕过内置类型的安全性,并为功能提供完全虚假的值。图书馆作家对此无能为力。
,因此10000不是有效的枚举值
这可能是正确的,但不是因为它不等于X1
或X2
。枚举没有拥有一个指定的枚举数。它可以保留其整数范围内的任何值。
现在,MYENUM
的实际范围取决于编译器,只要它选择的整数基础类型可以表示X1
和X2
即可。因此,例如,它可以是int8_t
,不能容纳10000。
(实际上,这里可能是int
。)
您将如何亲自找到解决方案?您是否会将地图访问权限包含在try块中并捕获异常?
是的,如果您愿意。
有许多方法可以对此类函数进行错误处理,无论它们是否涉及枚举。您可以抛出一个异常(.at()
调用已经为您完成了此操作,但是您可以捕获它并根据需要抛出自己类型的异常)。
您可以填充错误代码,返回占位符值,返回std::optional
…或忽略它,并证明函数用户必须传递名为 是enum
的成员,或者是某种“未定义的行为”的犯规(可能选择使函数的作用就像在这种情况下传递了X1
一样,因此它具有至少要做的事情。
所有常规选项。
如果我有很多函数可以通过用户输入的枚举值访问容器信息,那么您也可以尝试将它们全部捕获吗?
在选择输入参数错误处理方法时,确实要牢记这一点。
, class TagRes {
TagDict tagDict;
TagRes({this.tagDict});
TagRes.fromJson(Map<String,dynamic> json) {
tagDict =
json['tagDict'] != null ? new TagDict.fromJson(json['tagDict']) : null;
}
Map<String,dynamic> toJson() {
final Map<String,dynamic> data = new Map<String,dynamic>();
if (this.tagDict != null) {
data['tagDict'] = this.tagDict.toJson();
}
return data;
}
}
class TagDict {
Abc abc;
Abc def;
TagDict({this.abc,this.def});
TagDict.fromJson(Map<String,dynamic> json) {
abc = json['abc'] != null ? new Abc.fromJson(json['abc']) : null;
def = json['def'] != null ? new Abc.fromJson(json['def']) : null;
}
Map<String,dynamic> toJson() {
final Map<String,dynamic>();
if (this.abc != null) {
data['abc'] = this.abc.toJson();
}
if (this.def != null) {
data['def'] = this.def.toJson();
}
return data;
}
}
class Abc {
String helpHdr;
String helpText;
Abc({this.helpHdr,this.helpText});
Abc.fromJson(Map<String,dynamic> json) {
helpHdr = json['helpHdr'];
helpText = json['helpText'];
}
Map<String,dynamic>();
data['helpHdr'] = this.helpHdr;
data['helpText'] = this.helpText;
return data;
}
}
并没有本质上的危险,带有enum
参数的函数签名也不是坏习惯。在您的特定示例中,enum
仍然是有效的10000
,只是没有名字的人。
仅当在enum
中查找或使用std::map<MyEnum,Something>
时,这才成为问题。为了减轻这些问题,您可以对枚举值进行健全性检查:
switch (myEnum)
您甚至可以创建一个// specify a type for MyEnum explicitly so that we know we can fit values
// such as 100000
enum class MyEnum : unsigned {
X1 = 0,X2
};
// On a side note,enums are so small in size that it makes no sense to
// pass them by reference,simply pass them by value everywhere.
constexpr bool sanityCheck(MyEnum e) {
return e == MyEnum::X1 || e == MyEnum::X2;
}
int MyFunc(const MyEnum& input) {
assert(sanityCheck(input));
return mymap[input];
}
函数,该函数仅在发行版中进行编译,以使运行时成本为零。这比到处放置assert
更为有效。
但是最好的解决方案是在使用try-catch
创建MyEnum
时要小心。如果您不能100%确定该值具有名称,请不要将结果传递给接受static_cast
的函数。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。