【问题标题】:derived classes & type checking派生类和类型检查
【发布时间】:2013-01-28 19:27:55
【问题描述】:

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

【问题讨论】:

  • std::string派生是个坏主意。
  • NotAStringstd::string。所以你有一个类,用它自己的名字,不是一个字符串,而是一个字符串。我要喝点东西。

标签: c++ overloading typechecking typeid


【解决方案1】:

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

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

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

您尝试检查函数 inside 的类型永远不会起作用,此时编译器已经创建了一个 NotAString,而您所测试的只是 NotAString 参数是否为不是NotAString ...这显然行不通。

【讨论】:

    【解决方案2】:

    抛开糟糕的设计理念,改变这个构造函数...

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-20
      • 1970-01-01
      • 2011-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多