如何在C++中检查数据类型?
How to check data type in C++?
我是 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++ 中我需要做类似的事情,但这次每个字符都在链表的一个节点中,我需要再次将它们分开,链表中的整数和另一个链表中的字符串
与Python不同,C++ 是一种强类型语言。这意味着每个对象的类型在编译时是已知的。
话虽如此,但在某些情况下可以应用一个非常非常模糊的类比。
如果您有一个指向 class 至少有一个虚方法的对象的指针,dynamic_cast
会将其转换为指向请求的 class 的指针,或者一个nullptr
。只有当被指向的最派生对象在其层次结构中明确包含两个 classes 时,这才有效。
您似乎在挣扎的是 C++ 是一种静态和(相对)强类型的语言。为了讨论这些术语中的每一个的实际含义,我参考了 this other question,因为那里的解释可能比我能做的要好得多。
首先你应该确定你确实需要按照你目前尝试的方式做事。不要尝试写Python风格的代码。
也就是说,基本上有两种不同的方法可以实现类似于 Python(动态类型、鸭子类型,因此相对较弱的类型)允许您执行的行为:
使用 C++ 的内置动态类型机制。因此,您需要创建一个所谓的 多态基 class,即具有至少一个虚拟成员函数的 class(析构函数也可以工作,如果您没有定义的接口 - 它通常 必须 是虚拟的以避免讨厌的问题)。一个简短的例子:
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
s,您可以让用户决定其实际类型:
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
方法与此非常相似,除了您更明确地使用运行时类型信息并且不需要统一的接口(但为了维护您的代码需要做更多的工作) .
使用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;
}
}
};
如您所见,这需要大量工作。通过这种方法,您可以使用值语义,但无法轻松扩展 Value
以支持更多类型。此外,由于使用 union
,您将浪费一些内存。
底线:您需要自己实现行为,但可以完全按照您希望的方式实现。例如:您还可以实现执行隐式类型转换的赋值运算符 operator=(Value const &)
。您还可以使用 boost 的实现,例如 boost::any
或 boost::variant
.
我想参考我在本网站上针对同一主题写的两个答案,也许它们对您也有帮助:
还有一些相关的 C 代码,因为它试图解决同样的问题:
注意:此答案中的所有代码都是直接从内存中编写的,未经测试。因此,它仅作为基本技术的演示。
我是 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++ 中我需要做类似的事情,但这次每个字符都在链表的一个节点中,我需要再次将它们分开,链表中的整数和另一个链表中的字符串
与Python不同,C++ 是一种强类型语言。这意味着每个对象的类型在编译时是已知的。
话虽如此,但在某些情况下可以应用一个非常非常模糊的类比。
如果您有一个指向 class 至少有一个虚方法的对象的指针,dynamic_cast
会将其转换为指向请求的 class 的指针,或者一个nullptr
。只有当被指向的最派生对象在其层次结构中明确包含两个 classes 时,这才有效。
您似乎在挣扎的是 C++ 是一种静态和(相对)强类型的语言。为了讨论这些术语中的每一个的实际含义,我参考了 this other question,因为那里的解释可能比我能做的要好得多。
首先你应该确定你确实需要按照你目前尝试的方式做事。不要尝试写Python风格的代码。
也就是说,基本上有两种不同的方法可以实现类似于 Python(动态类型、鸭子类型,因此相对较弱的类型)允许您执行的行为:
使用 C++ 的内置动态类型机制。因此,您需要创建一个所谓的 多态基 class,即具有至少一个虚拟成员函数的 class(析构函数也可以工作,如果您没有定义的接口 - 它通常 必须 是虚拟的以避免讨厌的问题)。一个简短的例子:
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
s,您可以让用户决定其实际类型: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
方法与此非常相似,除了您更明确地使用运行时类型信息并且不需要统一的接口(但为了维护您的代码需要做更多的工作) .使用
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; } } };
如您所见,这需要大量工作。通过这种方法,您可以使用值语义,但无法轻松扩展
Value
以支持更多类型。此外,由于使用union
,您将浪费一些内存。
底线:您需要自己实现行为,但可以完全按照您希望的方式实现。例如:您还可以实现执行隐式类型转换的赋值运算符 operator=(Value const &)
。您还可以使用 boost 的实现,例如 boost::any
或 boost::variant
.
我想参考我在本网站上针对同一主题写的两个答案,也许它们对您也有帮助:
还有一些相关的 C 代码,因为它试图解决同样的问题:
注意:此答案中的所有代码都是直接从内存中编写的,未经测试。因此,它仅作为基本技术的演示。