【问题标题】:How to check data type in C++?如何在 C++ 中检查数据类型?
【发布时间】:2016-03-07 01:27:19
【问题描述】:

我对 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++ 中我需要做一些类似的事情,但是这次每个字符都在链表的一个节点中,我需要将它们、链表中的整数和另一个链表中的字符串分开

【问题讨论】:

  • 原版 C++ 中不存在。与 python 相比,c++ 是一种强类型语言。
  • 是的,我知道 C++ 是一个完全不同的级别,只是我有一个作业,我需要根据我正在评估的变量是 int 还是采取不同的行动方案一个字符串
  • 我还想补充一点,尽管有语言,这通常是一种“代码味道”(当然有一些合法的用例)
  • 问题是,我从 txt 文件中获取操作,例如 3+2,然后我正在创建一个链表来存储该操作,txt 文件中的每个项目都被存储作为一个对象,所以列表最终是这样的:->3->+->2。然后我必须把它分开,一个列表中的数字,另一个列表中的字符。所以我必须将每个值作为字符串检查,但我仍然需要评估字符串是否包含数字或 int,以便我可以将数字与字符分开
  • @JojOatXGME 您所描述的是“静态类型”(这也是 OP 遇到的问题)。 “强类型”意味着值具有单一的固定类型。这种类型不需要在编译时知道。 lisp 就是这种语言(强大但动态的类型)的一个例子。

标签: c++ types isinstance


【解决方案1】:

您似乎在纠结的是 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
      }
    };
    

    现在您可以使用它来存储 Values 的实际类型,您可以让用户决定:

    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++ 的内置动态类型,您需要不使用值语义,而是完全使用引用语义,或者使用真正的引用,或者(在大多数必须转移所有权的情况下,如上例中的 values矢量)使用指针。

    dynamic_cast 方法的工作原理与此非常相似,只是您更明确地使用运行时类型信息并且不需要统一的接口(但为了维护您的代码需要做更多的工作)。

  2. 使用union 语言功能。只有在 C++11 中,这才真正成为可能,其中联合成员可能难以解释:

    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;
        }
      }
    };
    

    如您所见,这是一项相当多的工作。使用这种方法,您可以使用值语义,但不能轻松扩展您的 Values 以支持更多类型。此外,由于使用了union,你会浪费一些内存。

底线:您需要自己实现该行为,但可以完全按照您希望它的行为方式实现。例如:您还可以实现赋值运算符operator=(Value const &amp;) 进行隐式类型转换。您还可以使用 boost 中的实现,例如 boost::anyboost::variant

我想参考我在这个网站上写的关于同一主题的两个答案,也许它们对你也有帮助:

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

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

【讨论】:

  • +1: 用于指出多态基类,以便我进一步研究和学习新东西!
【解决方案2】:

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

话虽如此,但有一个非常非常模糊的类比适用于某些情况。

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

【讨论】:

  • " 强类型语言。这意味着每个对象的类型在编译时是已知的。"不。那是您在此处描述的静态类型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-24
  • 1970-01-01
  • 2010-12-10
相关资源
最近更新 更多