派生类和类型检查

时间:2013-01-28 19:27:56

标签: c++ overloading typechecking typeid

我正在尝试编写一个方法,该方法将从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类或执行一些更严格的类型检查以使其按照我的方式工作?

2 个答案:

答案 0 :(得分:2)

问题是您的NotAString(std::string str)构建器不是explicit因此它允许从std::stringNotAString的隐式转换。

当您使用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