Як отримати тип змінної?


130

Як у C ++ як можна знайти тип змінної?



7
cout << typeid (змінна) .name () << endl;
SRN

2
Використовуйте пошук або Google :) stackoverflow.com/questions/81870/print-variable-type-in-c Theharshest швидко: D
Kariboo

14
@Kariboo, я скористався Google, і він надіслав мене сюди.
Майкл Уорнер

Це питання є дуже незрозумілим, як воно є, і навіть після бачення різних відповідей; аж ніяк не ясно, що питання шукає прийнятої відповіді.
Антті Хаапала

Відповіді:


158

Ви можете використовувати оператор typeid :

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

15
@David - Так iозначає ціле число вашого компілятора. Імена, що повертаються, не визначені стандартом.
Бо Персон

11
Коли я використовую його на vector <int>, він повертає St6vectorIiSaIiEE. WTF?
Боян Кушльов

2
@BobbyBrown ви не самотні !! google.co.uk/webhp#safe=off&q=St6vectorIiSaIiEE
Rich O'Kelly

5
Імена, що повертаються typeid, дуже скорочено, залежать від компілятора і не призначені для споживання людиною. Ви можете "демангувати" їх (це фактичний термін!), Або в коді з чимось на зразок gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html , з утилітами командного рядка, такими як c++filt, або з будь-якими різними онлайн-демонтажами наприклад demangler.com .
cincodenada

33

Для статичних тверджень введено C ++ 11, decltypeщо є досить корисним у певних сценаріях.



9

Основна відмінність C ++ від Javascript полягає в тому, що C ++ є мовою статичного типу, wile javascript - динамічним.

У динамічних набраних мовах змінна може містити будь-яку річ, а її тип задається значенням, яке вона має, мить за моментом. У мовах, що набираються статично, тип змінної оголошується і не може змінюватися.

Тут можуть бути динамічна диспетчеризація та композиція об'єктів та підтипів (успадкування та віртуальні функції), а також статична диспетчеризація та властивість (через шаблон CRTP), але у будь-якому випадку тип змінної повинен бути відомий компілятору.

Якщо ви не можете знати, що це таке, чи може бути, це тому, що ви створили щось, оскільки мова має динамічну систему типу.

Якщо це так, вам краще переосмислити свій дизайн, оскільки він йде в землю, не природну для мови, якою ви користуєтесь (найбільше, як їхати по автостраді з гусеницею або у воді з машиною)


Якщо C ++ має динамічні зміни, то я думаю, що це було б чудово, і typeof і parseInt, функції parseFloat також стануть корисними, але я не знаю, чому виробники C ++ роблять це занадто важким, наприклад! хто каже, що добре писати cout << "Рядок"
Waqas Tahir

визначення найкраще !!!! #include <sstream> string str ("1912"); int strtointval; stringstream (str) >> strtointval;
Waqas Tahir

@Waqas Uh, що? Люди, які кажуть, що це найкраще, - це люди, які визначають мову, і IMO у них є майже остаточним словом у будь-якому відношенні до цього - наприклад, хороших методах кодування, наприклад. Чи можете ви перефразувати цей коментар, щоб він мав більше сенсу?
Фонд позову Моніки

Я абсолютно не згоден. Java, C #, PHP, Perl, Python тощо, були розроблені на C і C ++, і вони не є гусеницями. (Коли ви створюєте додаток для баз даних для відкриття змінних таблиць із "невідомих" баз даних, вам потрібно керувати типом поля до змінної схеми та віри "дуже" диманським способом;))
TomeeNS

@TomeeNS: Ні. Вони написані на С і С ++, не розроблені . Вони розроблені, щоб виконувати свою роботу. Вони мають динамічний тип, навіть якщо самі C і C ++ цього не роблять. З цим нічого дивного.
Еміліо Гаравалья

8

Зазвичай, бажати знайти тип змінної в C ++ - це неправильне питання. Це, як правило, щось, що ви використовуєте з процедурних мов, наприклад, C або Pascal.

Якщо ви хочете кодувати різні форми поведінки залежно від типу, спробуйте дізнатися, наприклад, про перевантаження функцій та успадкування об'єктів . Це не матиме негайного сенсу у ваш перший день C ++, але продовжуйте це.


Не дуже, скажімо, у вас є клас "Об'єкт" та "підклас" Книга. Тепер уявіть, що у вас є Коробка, яка може зберігати безліч предметів, але ви чомусь хочете перерахувати всі Книги всередині неї. Перевірка типу набагато чистіша, тоді потрібно додати метод "type" до "Object", а потім замінити його на Book, щоб повернути щось на кшталт "книга"
Пауло Сезар,

Як і будь-яке правило, є винятки (отже, моє "зазвичай"!), І контейнери, як правило, додають складності теорії типів. Я ніколи не перекривав контейнери з поліморфних об'єктів ... У більшості випадків шаблони єдиних типів контейнерів є достатніми та набагато чистішими.
Pontus Gagge

Ви не використовуєте шаблони?
Брайан Грейс

6

Я вважаю, що у мене є дійсний випадок використання для використання typeid (), так само, як і для sizeof (). Для функції шаблону мені потрібно виділити особливий регістр коду на основі змінної шаблону, щоб я запропонував максимальну функціональність та гнучкість.

Набагато більш компактне і бездоганне, ніж використання поліморфізму, створити один екземпляр функції для кожного підтримуваного типу. Навіть у такому випадку я міг би скористатися цим трюком, щоб записати тіло функції лише один раз:

Зауважте, що оскільки в коді використовуються шаблони, викладений нижче переклад повинен статично вирішуватися лише в один блок коду, оптимізуючи всі помилкові випадки, 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: Мені не вдалося використати typeid () на Arduino. Також typeid () - це перевірка часу виконання , а не час компіляції, тому його не можна використовувати для генерації оптимізованого коду.
Ден Труонг

1
Так, ні, це не те, що ви думали, що це робиться. typeidпросто не може бути статичною перевіркою часу компіляції - за визначенням - тому це не сприяє оптимізації. For a template function, I need to special case the code based on the template variableТак, то, що ви дійсно хочете, це статичний поліморфізм через ідіому CRTP. Саме цього і досягають.
підкреслюй_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

Сподіваюся, це допомагає.

EDIT: На жаль, ось найскладніший випадок, про який я можу придумати: наявність глобальної змінної невідомого типу. У цьому випадку вам знадобиться c ++ 14 та змінна шаблону.

Щось на зразок цього:

template<typename T> vector<T> global_var;

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

Це все ще трохи нудно, але це так само близько, як ви можете дістатися до безкінечних мов. Просто переконайтеся, що коли ви посилаєтесь на змінну шаблону, завжди кладіть туди специфікацію шаблону.



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

Зауважте, як перше, так і друге, якщо це працює.


Розпізнавання типу за першим символом - дуже погана ідея.
Дмитро Кузьмінов

Чи можете ви бути більш конкретним Дмитро? Я не зрозумів тут.
Пікачу

Це можна просто скоротити std::cout << "I'm a variable of type " << typeid(n).name(). (перероблено для запобігання артефактам, але це можна виправити за допомогою іншої перевірки). Навіть тоді, якщо ви абсолютно хочете порівняння, так набагато краще зробитиtypeid(n) == typeid(int)
Зої
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.