Bir değişkenin türünü nasıl elde ederim?


130

C ++ 'da, bir değişkenin türü nasıl bulunur?



7
cout << typeid (değişken) .name () << endl;
SRN

2
Aramayı kullanın veya google :) stackoverflow.com/questions/81870/print-variable-type-in-c Theharshest hızlıdır: D
Kariboo

14
@Kariboo, Google'ı kullandım ve beni buraya gönderdi.
Michael Warner

Bu soru olduğu gibi çok belirsizdir ve çeşitli cevapları gördükten sonra bile; sorunun kabul edilen cevabı aradığı hiçbir şekilde açık değildir.
Antti Haapala

Yanıtlar:


158

Typeid operatörünü kullanabilirsiniz :

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

15
@David - Yani iderleyicinizdeki tam sayı anlamına gelir. Döndürülen isimler standart tarafından belirtilmemiştir.
Bo Persson

11
<int> vektöründe kullandığımda St6vectorIiSaIiEE döndürüyor. O NE LAN?
Boyan Kushlev


5
Tarafından döndürülen adlar typeidçok kısaltılmıştır, derleyiciye özeldir ve insan tüketimi için tasarlanmamıştır. Şunları yapabilirsiniz "demangle" Onları (o fiili terim!), Ya gibi bir şeyle kodunda gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html gibi komut satırı uygulamaları ile, c++filtveya çeşitli çevrimiçi demanglers herhangi biriyle demangler.com gibi .
cincodenada

33

Statik iddialar için, decltypebelirli senaryolarda oldukça kullanışlı olan C ++ 11 tanıtıldı .


12

Bir değişkeniniz varsa

int k;

Türünü kullanarak alabilirsiniz

cout << typeid(k).name() << endl;

SO'da şu konu başlığına bakın: Benzer soru


9

C ++ ve Javascript arasındaki temel fark, C ++ 'nın statik tipte bir dil olmasıdır, wile javascript dinamiktir.

Dinamik tipli dillerde bir değişken her şeyi içerebilir ve türü an be an tuttuğu değerle verilir. Statik yazılan dillerde bir değişkenin türü bildirilir ve değiştirilemez.

Dinamik gönderme ve nesne oluşturma ve alt tipleme (kalıtım ve sanal işlevler) yanı sıra statik gönderme ve süper tipleme (şablon CRTP aracılığıyla) olabilir, ancak her durumda değişkenin türü derleyici tarafından bilinmelidir.

Ne olduğunu veya ne olabileceğini bilemeyecek bir konumdaysanız, bunun nedeni dilin dinamik bir yazı sistemine sahip olması nedeniyle bir şey tasarlamış olmanızdır.

Eğer durum buysa, kullandığınız dil için doğal olmayan bir ülkeye gireceği için tasarımınızı yeniden düşünmeniz daha iyi olur (en çok tırtılla otoyolda veya araba ile suda gitmek gibi)


Eğer C ++ dinamik değişime sahipse, o zaman bunun harika olacağını ve typeof ve parseInt olacağını düşünüyorum, parseFloat işlevleri de işe yarayacak, ancak C ++ üreticilerinin bunu neden bu kadar zorlaştırdığını bilmiyorum, örneğin! cout yazmanın iyi olduğunu söyleyenler << "String"
Waqas Tahir

kararlılık en iyisidir !!!! #include <sstream> string str ("1912"); int strtointval; stringstream (str) >> strtointval;
Waqas Tahir

@Waqas Uh, ne var? Bunun en iyisi olduğunu söyleyen insanlar, dili tanımlayan kişilerdir ve onunla ilgili her konuda son sözü onlar verir - örneğin, iyi kodlama uygulamaları. Bu yorumu daha mantıklı olacak şekilde yeniden ifade edebilir misiniz?
Fund Monica'nın Davası

Ben kesinlikle katılmıyorum. Java, C #, PHP, Perl, Python vb. C ve C ++ ile tasarlanmışlardır ve tırtıllar değildir. ('Bilinmeyen' veritabanlarından değişken tabloları açmak için bir veritabanı uygulaması oluşturduğunuzda, alan türünü değişken şemaya ve 'çok' dinamik bir şekilde kötü veraya kontrol etmeniz gerekir;))
TomeeNS

@TomeeNS: Hayır. C ve C ++ ile yazılmıştır , tasarlanmamışlardır . İşlerini yapmak için tasarlanmışlardır. C ve C ++ kendileri yapmasa bile dinamik tipe sahiptirler. Bu garip bir şey değil.
Emilio Garavaglia

8

Genellikle, C ++ 'da bir değişkenin türünü bulmak istemek yanlış sorudur. C veya Pascal gibi prosedürel dillerden taşıdığınız bir şey olma eğilimindedir.

Türe bağlı olarak farklı davranışları kodlamak istiyorsanız, örneğin fonksiyon aşırı yükleme ve nesne mirası hakkında bilgi edinmeye çalışın . Bu, ilk C ++ gününüzde hemen bir anlam ifade etmeyecek, ancak devam edin.


Pek sayılmaz, diyelim ki bir sınıf Nesneniz ve bir alt sınıf Kitabınız var. Şimdi çok sayıda Nesneyi saklayabilen bir Kutunuz olduğunu hayal edin, ancak bir nedenle içindeki tüm Kitapları listelemek istiyorsunuz. Türünü kontrol etme daha temiz ardından "kitabı" gibi dönüşüne Kitap şey onu nesne için bir yöntem "türü" ekleyin ve sonra geçersiz kılmak zorunda olduğu
Paulo Cesar

Herhangi bir kuralda olduğu gibi, istisnalar vardır (bu nedenle benim 'genellikle' benim!) Ve kaplar tip teorisine karmaşıklık ekleme eğilimindedir. Polimorfik nesnelerden oluşan kaplara hiç bu kadar düşkün olmadım… çoğu durumda, şablonlu tek tip kap türleri yeterli ve çok daha temiz.
Pontus Gagge

Şablon kullanmıyor musunuz?
Bryan Grace

6

Typeid () kullanmak için geçerli bir kullanım örneğim olduğuna inanıyorum, aynı sizeof () kullanmak için geçerli olduğu gibi. Bir şablon işlevi için, maksimum işlevsellik ve esneklik sunabilmem için, şablon değişkenine dayalı olarak kodu özel bir duruma getirmem gerekir.

Desteklenen her tür için işlevin bir örneğini oluşturmak, polimorfizm kullanmaktan çok daha kompakt ve bakımı yapılabilir. Bu durumda bile, işlevin gövdesini yalnızca bir kez yazmak için bu numarayı kullanabilirim:

Kod şablonlar kullandığından, aşağıdaki switch ifadesinin statik olarak tek bir kod bloğuna çözümlenmesi ve tüm yanlış durumları (AFAIK) ortadan kaldırması gerektiğini unutmayın.

T bir türe karşı diğeri ise, bir dönüşümü ele almamız gerekebilecek bu örneği düşünün. Bunu, donanımın myClassA veya myClassB türünü kullanacağı donanıma erişmek için sınıf uzmanlığı için kullanıyorum. Bir uyumsuzluk durumunda, verileri dönüştürmek için zaman harcamam gerekiyor.

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'da typeid () kullanamadım. Ayrıca typeid () bir çalışma zamanı kontrolüdür, derleme zamanı değildir, dolayısıyla optimize edilmiş kod üretmek için kullanılamaz.
Dan Truong

1
Evet, hayır, bu sandığın şeyi yapmıyor. typeidstatik, derleme zamanı denetimi olamaz - tanım gereği - bu nedenle bu herhangi bir optimizasyonu kolaylaştırmaz. For a template function, I need to special case the code based on the template variableDoğru, yani gerçekten istediğiniz şey, CRTP deyimi aracılığıyla statik polimorfizmdir. Bu tam olarak bunu başarır.
underscore_d

4

Cevabımın yardımcı olup olmayacağından emin değilim.

Kısa cevap, onu kullanmak için bir değişkenin türünü gerçekten bilmenize gerek yoktur / bilmek istemezsiniz.

Statik değişkene bir tür vermeniz gerekiyorsa, o zaman basitçe auto kullanabilirsiniz.

Bir sınıfta veya yapıda "auto" kullanmak istediğiniz daha karmaşık bir durumda, decltype ile şablon kullanmanızı öneririm.

Örneğin, başka birinin kitaplığını kullandığınızı ve "bilinmeyen_var" adında bir değişkeni olduğunu ve bunu bir vektör veya yapıya koymak istediğinizi varsayalım, bunu tamamen yapabilirsiniz:

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

Bu yardımcı olur umarım.

DÜZENLEME: İyi bir ölçü için, işte aklıma gelen en karmaşık durum: bilinmeyen türde küresel bir değişkene sahip olmak. Bu durumda c ++ 14 ve şablon değişkenine ihtiyacınız olacaktır.

Bunun gibi bir şey:

template<typename T> vector<T> global_var;

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

Hala biraz sıkıcı ama yazısız dillere olabildiğince yakın. Şablon değişkenine başvurduğunuzda, daima şablon özelliğini oraya yerleştirdiğinizden emin olun.


2
#include <typeinfo>

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

0

Bir sınıf ile bilinen bir tür arasında bir karşılaştırma yapmanız gerekirse, örneğin:

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

Bu karşılaştırma satırını kullanabilirsiniz:

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

bu, typeidadın dize türünü içerdiğini kontrol eder (typeid adında başka karıştırılmış veriler vardır, bu nedenle en iyisi bir s1.find(s2)yerine yapmaktır ==).


-2

typeid(x).name()X'in değişken adı olduğu yere kesinlikle gidebilirsiniz . Aslında veri türüne bir const char gösterici döndürür. Şimdi aşağıdaki koda bakın.

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

Her ikisinin de işe yaradığına dikkat edin.


Yazıyı ilk karakterden tanımak çok kötü bir fikir.
Dmitry Kuzminov

Lütfen biraz daha açık konuşabilir misin Dmitry? Burada amacını anlamadım.
Pikachu

Bu sadece kısaltılabilir std::cout << "I'm a variable of type " << typeid(n).name(). (a / an artefaktları önlemek için yeniden ifade edildi, ancak bu başka bir kontrolle düzeltilebilir). O zaman bile, kesinlikle bir karşılaştırma istiyorsanız, yapmak çok daha iyitypeid(n) == typeid(int)
Zoe
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.