如何在C ++中检查数据类型?

时间:2016-03-07 01:27:19

标签: c++ types isinstance

我对C ++很新,我主要使用python。我试图检查我正在处理的对象中存储的值的变量类型。我记得在Python中有一个命令isinstance我可以用它作为运行某些命令的条件,比如下一个值是字符串,做A,如果它是一个int做B

有没有办法快速检查C ++中变量的数据类型是什么?

示例:

在python中,我有一个带有数学运算的数组,每个字符都在一个字段中

[3,"+",2]

当我读取数组时,我会使用isinstance命令将字符串与字符串分开

if isinstance(list[0],int):
        aux1.append(list[0])
        list=list[1:] 
    else:
        if isinstance(lista[0],str):
            aux2.append(list[0
            list=list[1:]

现在在C ++中我需要做类似的事情,但这次每个字符都在一个链接列表的节点中,我需要将它们分开,在链表中分隔,在另一个链表中包含字符串

2 个答案:

答案 0 :(得分:2)

你似乎正在努力的是C ++是一种静态和(相对)强类型的语言。关于这些术语实际上意味着什么的讨论,请参考this other question,因为它的解释可能比我更好。

首先,你应该确定你实际上需要按照你目前的方式做事。不要试图编写Python样式代码。

也就是说,基本上有两种不同的方法可以实现类似于Python(动态类型,鸭子类型,因此相对较弱的类型)允许你这样做的行为:

  1. 使用C ++的内置动态类型机制。因此,您需要创建一个所谓的多态基类,这是一个至少具有一个虚拟成员函数的类(如果您没有定义的接口,则析构函数也可以工作 - 最常见的是也必须虚拟以避免讨厌的问题)。一个简短的例子:

    struct Value {
      virtual void write_to(std::ostream &) const = 0;
      virtual void read_from(std::istream &) = 0;
      virtual ~Value() {} // Absolutely required!!!
    };
    struct Number : public Value {
      int data;
      void write_to(std::ostream & stream) const {
        stream << "<Number " << data << ">";
      }
      void read_from(std::istream & stream) {
        stream >> data; // Not the same format as write_to, shame on me
      }
      // Implicit destructor is fine
    };
    struct String : public Value {
      std::string data;
      void write_to(std::ostream & stream) const {
        stream << "<String " << data.size() << " " << data << ">";
      }
      void read_from(std::istream & stream) {
        stream >> data; // Not the same format as write_to, shame on me
      }
    };
    

    使用此功能,您现在可以存储Value的实际类型,供用户自行决定:

    std::vector<std::unique_ptr<Value>> values;
    while (wantsToEnterMoreValues) {
      std::string choice = ask("What type of value do you want to enter?");
      std::unique_ptr<Value> value;
      if (choice == "string") {
        value = std::make_unique<String>();
      } else if (choice == "number") {
        value = std::make_unique<Number>();
      } else {
        // launch apocalypse
      }
      value->read_from(std::cin);
      values.push_back(value);
    }
    

    这可以轻松扩展到更多类型。请注意,为了使用C ++的内置动态类型,您需要不使用值语义,而是完全使用引用语义,使用实际引用,或者(在大多数情况下必须将所有权转移到上面的示例中{{1}使用指针。

    values方法与此非常相似,不同之处在于您更明确地使用运行时类型信息,并且不需要统一的接口(但为了维护代码还有更多的工作)。 / p>

  2. 使用dynamic_cast语言功能。这只能在C ++ 11中实现,其中union成员可能是非平凡的构造:

    union

    正如你所看到的,这相当多的工作。使用这种方法,您可以使用值语义,但不能轻易扩展enum class Type { Number, String }; struct Value { Type type; union { std::string string; int number; }; Value(std::string const & s) : type(Type::String), string(s) {} Value(int n) : type(Type::Number), number(n) {} Value(Value const & v) : type(v.type) { switch (type) { case Type::Number: number = v.number; break; case Type::String: new (&string) std::string(v.string); break; default: break; // Launch nuclear missiles } } ~Value() { switch (type) { case Type::String: string.~std::string(); break; default: break; } } }; 以支持更多类型。此外,由于使用了Value,你会浪费一些记忆。

  3. 底线:您需要自己实现行为,但可以按照您希望的方式执行此操作。例如:您还可以实现执行隐式类型转换的赋值运算符union。您还可以使用提升中的实施,例如operator=(Value const &)boost::any

    我想将我在本网站上撰写的两个答案引用到同一主题,也许它们对您也有帮助:

    也是一些相关的C代码,因为它试图解决同样的问题:https://stackoverflow.com/a/35443434/1116364

    注意:此答案中的所有代码都是直接写入内存而未经过测试。因此,它仅用作基本技术的演示。

答案 1 :(得分:0)

与Python不同,C ++是一种强类型语言。这意味着每个对象的类型在编译时都是已知的。

话虽如此,在某些情况下,有一个非常非常模糊的类比可以适用。

如果您有一个指向其类至少有一个虚方法的对象的指针,则dynamic_cast会将其转换为指向所请求类的指针,或转换为nullptr。这只有在被指向的最派生对象明确地包含其层次结构中的两个类时才有效。