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

Twhite1195

我对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样式代码。

也就是说,基本上可以通过两种不同的方法来实现与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 &)进行隐式类型转换的赋值运算符您也可以使用boost的实现,例如boost::anyboost::variant

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

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

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

Related 相关文章

热门标签

归档