我正在尝试编写一个方法,该方法将从std :: string派生的类作为参数。该方法超载了几个不同的功能签名。如果我尝试使用std :: string调用它,或者至少是运行时错误,但我觉得编译失败了,但显然编译器对我来说太聪明了。
class NotAString : public std::string {
NotAString(std::string str) : std::string(str) { }
};
class Foo {
Foo();
void bar(NotAString);
void bar(int)
};
编译并运行
Foo foo();
foo.bar(NotAString("baz"));
但是这样做:
Foo foo();
foo.bar(std::string("baz"));
我尝试过像这样使用typeid(str):
void Foo::Bar(NotAString str) {
if(typeid(&str) != typeid(new NotAString()) {
throw std::bad_typeid();
}
}
但是如果传递给std :: string或NotAString,它总是抛出异常。我尝试过像这样使用dynamic_cast:
void Foo::Bar(NotAString str) {
if (dynamic_cast<NotAString*>(&str) == NULL) {
throw std::bad_type();
}
}
但它永远不会抛出异常。
目标是能够区分字符串和表示键值查找键的字符串。如何更改我的NotAString类或执行一些更严格的类型检查以使其按照我的方式工作?
答案 0 :(得分:2)
问题是您的NotAString(std::string str)
构建器不是explicit
因此它允许从std::string
到NotAString
的隐式转换。
当您使用std::string
调用该函数时,编译器会注意到您可以通过构造函数转换参数来调用它,因此它会创建一个NotAString
临时函数并将其传递给函数。
如果您声明它explicit NotAString(std::string str)
,那么它将不允许这些隐式转换。
您尝试检查内部函数的尝试永远不会起作用,此时编译器已创建NotAString
并且您正在测试的是{{1}参数不是NotAString
......显然不会起作用。
答案 1 :(得分:0)
除了糟糕的设计理念外,更改此构造函数......
class NotAString : public std::string {
NotAString(std::string str) : std::string(str) { }
};
...成为explicit
:
class NotAString : public std::string {
explicit NotAString(std::string str) : std::string(str) { }
};
这会阻止std::string
个对象在用作函数参数时被无效转换为NotAString
。