如何获取变量的类型?


130

在C ++中,如何找到变量的类型?



7
cout << typeid(variable).name()<< endl;
SRN 2012年

2
使用搜索或谷歌:) stackoverflow.com/questions/81870/print-variable-type-in​​-c Theharshest是最快的:D
Kariboo

14
@Kariboo,我用过Google,它把我送到了这里。
迈克尔·沃纳

即使在看到各种答案之后,这个问题仍然非常不清楚。尚不清楚该问题正在寻找被接受的答案。
Antti Haapala'9

Answers:


156

您可以使用typeid运算符

#include <typeinfo>
...
cout << typeid(variable).name() << endl;

15
@David-因此i意味着编译器上的整数。返回的名称不是由标准指定的。
Bo Persson

11
当我在vector <int>上使用它时,它返回St6vectorIiSaIiEE。WTF?
Boyan Kushlev '16


5
返回的名称typeid非常缩写,特定于编译器,并不供人类使用。您可以使用诸如gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html之类的代码在代码中使用“ demangle”它们(这是实际术语!),使用诸如的命令行实用程序c++filt或使用各种在线demanglers中的任何一个如demangler.com
cincodenada

33

对于静态断言,引入了C ++ 11 decltype,在某些情况下非常有用。



9

C ++和Javascript之间的主要区别在于C ++是一种静态类型的语言,而javascript是动态的。

在动态类型语言中,变量可以包含任何东西,其类型由其持有的值随时提供。在静态类型语言中,变量的类型是声明的,并且不能更改。

可以有动态分派,对象组成和子类型化(继承和虚拟函数),以及静态分派和超类型化(通过模板CRTP),但是在任何情况下,编译器都必须知道变量的类型。

如果您不知道它是什么或者可能是什么,那是因为您设计了某种东西,因为该语言具有动态类型系统。

如果是这种情况,您最好重新考虑一下设计,因为它进入的语言对您而言并不自然(最像是骑着毛毛虫在高速公路上,或者是坐汽车在水中)


如果C ++具有动态变化,那么我认为它会很棒,并且typeof和parseInt,parseFloat函数也将派上用场,但是我不知道为什么C ++编写者会使其变得太难!谁说写cout <<“ String”很不错
Waqas Tahir

决心是最好的!#include <sstream>字符串str(“ 1912”); int strtointval; stringstream(str)>> strtointval;
Waqas Tahir 2015年

@Waqas呃,什么?说最好的人就是定义语言的人,而IMO在与语言有关的任何事情上都有最终决定权-例如良好的编码习惯。您可以改写该评论,这样更有意义吗?
基金莫妮卡的诉讼

我完全不同意。Java,C#,PHP,Perl,Python等是用C和C ++设计的,它们不是毛毛虫。(当您创建数据库应用程序以从“未知”数据库中打开变量表时,您需要以“非常”动态的方式控制字段类型,变量方案以及
反之

@TomeeNS:不。它们是 C和C ++ 编写的,不是经过设计的。它们是专为完成工作而设计的,即使C和C ++本身没有,它们也具有动态类型。这没什么奇怪的。
Emilio Garavaglia '10

8

通常,想要在C ++中找到变量的类型是一个错误的问题。它往往是您从过程语言(例如C或Pascal)中获得的东西。

如果要根据类型编写不同的行为代码,请尝试了解有关函数重载对象继承的信息。在您使用C ++的第一天,这不会立即生效,但请继续努力。


并非如此,假设您有一个Object类和一个Book子类。现在,假设您有一个可以存储很多对象的Box,但是由于某种原因,您希望列出其中的所有Book。检查类型要干净得多,然后必须向Object添加方法“ type”,然后在Book上重写它以返回类似“ book”的内容
Paulo Cesar

与任何规则一样,也有例外(因此,我通常是这样!),容器的确会给类型理论增加复杂性。我从未对多态对象的容器感到满意……在大多数情况下,模板化的统一容器类型就足够了,而且更加干净。
Pontus Gagge

您不使用模板吗?
Bryan Grace

6

我相信我有一个使用typeid()的有效用例,就像使用sizeof()一样有效。对于模板功能,我需要对基于模板变量的代码进行特殊处理,以便提供最大的功能和灵活性。

与使用多态性相比,它为每种支持的类型创建一个函数实例比使用多态性更为紧凑和可维护。即使在那种情况下,我也可能使用此技巧只编写一次函数主体:

请注意,由于代码使用模板,因此以下switch语句应静态地解析为一个代码块,从而优化了所有错误情况AFAIK。

考虑这个例子,如果T是一种类型而不是另一种类型,我们可能需要处理转换。我使用它进行类专业化访问硬件,其中硬件将使用myClassA或myClassB类型。如果不匹配,我需要花时间转换数据。

switch ((typeid(T)) {
  case typeid(myClassA):
    // handle that case
    break;
  case typeid(myClassB):
    // handle that case
    break;
  case typeid(uint32_t):
    // handle that case
    break;
  default:
    // handle that case
}

1
TypeId:我无法在Arduino上使用typeid()。另外,typeid()是运行时检查,不是编译时,因此不能用于生成优化的代码。
Dan Truong

1
是的,不,这不符合您的想象。typeid根据定义,它根本不能是静态的编译时检查,因此这不利于任何优化。For a template function, I need to special case the code based on the template variable是的,所以您真正想要的是通过CRTP习惯用法实现的静态多态性。这正是实现的目标。
underscore_d

4

我不确定我的回答是否会有所帮助。

简短的答案是,您实际上并不需要/不想知道使用变量的类型。

如果您需要为静态变量指定类型,则可以简单地使用auto。

在更复杂的情况下,如果您想在类或结构中使用“自动”,我建议使用带decltype的模板。

例如,假设您正在使用其他人的库,并且该库具有一个名为“ unknown_var”的变量,并且希望将其放入向量或结构中,则可以完全这样做:

template <typename T>
struct my_struct {
    int some_field;
    T my_data;
};
vector<decltype(unknown_var)> complex_vector;
vector<my_struct<decltype(unknown_var)> > simple_vector

希望这可以帮助。

编辑:好的措施,这是我能想到的最复杂的情​​况:具有未知类型的全局变量。在这种情况下,您将需要c ++ 14和template变量。

像这样:

template<typename T> vector<T> global_var;

void random_func (auto unknown_var) {
    global_var<decltype(unknown_var)>.push_back(unknown_var);
}

它仍然有些乏味,但与无类型语言一样近。只要确保每当您引用模板变量时,就始终将模板规范放在此处。


2
#include <typeinfo>

...
string s = typeid(YourClass).name()

0

如果需要在类和已知类型之间进行比较,例如:

class Example{};
...
Example eg = Example();

您可以使用以下比较行:

bool isType = string( typeid(eg).name() ).find("Example") != string::npos;

该命令检查typeid名称是否包含字符串类型(typeid名称包含其他损坏的数据,因此最好使用s1.find(s2)代替==)。


-2

您绝对可以在typeid(x).name()其中x是变量名的地方使用。实际上,它返回一个指向数据类型的const char指针。现在,看下面的代码。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n = 36;
    char c = 'A';
    double d = 1.2;
    if(*(typeid(n).name()) == 'i'){
        cout << "I am an Integer variable" << endl;
    }
    if(*((char *) typeid(d).name()) == 'd'){
        cout << "I am a Double variable" << endl;
    }
    if(*((char *) typeid(c).name()) == 'c'){
        cout << "I am a Char variable" << endl;
    }
    return 0;
}

请注意,如果两者都有效,那么第一和第二如何工作。


用第一个字符识别类型是一个非常糟糕的主意。
德米特里·库兹米诺夫

能否请您更具体些Dmitry?我没有明白你的意思。
皮卡丘

可以将其缩短为std::cout << "I'm a variable of type " << typeid(n).name()。(改写以防止出现伪影,但可以通过其他检查来解决)。即使这样,如果您绝对希望进行比较,那就更好了typeid(n) == typeid(int)
Zoe
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.