0

我正在尝试编写一个方法,它将派生自 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 类或通过编译器强制执行一些更严格的类型检查,以使其按我的意愿工作?

4

2 回答 2

2

问题是您的NotAString(std::string str)构造函数不是这样,它允许从toexplicit隐式转换。std::stringNotAString

当您使用编译器调用函数时std::string,编译器会注意到您可以通过构造函数转换参数来调用它,因此它会创建一个NotAString临时变量并将其传递给函数。

如果您声明它,explicit NotAString(std::string str)那么它将不允许那些隐式转换。

您检查函数内部类型的尝试永远不会起作用,到那时编译器已经创建 aNotAString并且您要测试的只是NotAString参数是否不是NotAString... 这显然不会起作用。

于 2013-01-28T19:30:28.900 回答
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用作函数参数时被隐式转换为。

于 2013-01-28T19:31:42.700 回答