2015-09-22 5 views
51

Я видел, что для того, чтобы проверить, является ли тип T класса можно использовать:Почему нет типа std :: is_struct?

bool isClass = std::is_class<T>::value; 

Он возвращает истину для обоего классов и структур. Я знаю, что в C++ они почти одно и то же, но я хотел бы знать, почему между ними нет различия в типе. Всегда ли бесполезно проверять эту разницу, или есть еще одна причина, которую я не понимаю?

+12

Структуры и классы не являются «почти одинаковыми»; они на самом деле точно такие же * тип вещи *, но они имеют два разных * синтаксических представления * с разными * стандартными * режимами доступа. В объявлении типа, которое делает все спецификаторы доступа явным, то есть '(struct | class) MyClass: public BaseClass {private: ....', есть * no * разница между 'struct' и' class'. –

+3

Очень рекомендуемый [выбранный ответ] (http://stackoverflow.com/a/34108140/464581) - это просто неправильно, дезинформация. Теперь есть два правильных ответа: один короткий и один длинный. Выберите правильный ответ, чтобы читатели, приезжающие сюда через Google, не были полностью введены в заблуждение и дезинформированы. –

+1

@ Cheersandhth.-Alf: Что вы утверждаете, это неправильно? Вы говорите, что C++ имеет понятие «структура», которое на самом деле является отдельным и отличным от понятия «класс»? Или вы утверждаете, что ответ должен сказать, что структуры и классы - это то же самое, что и два ключевых слова, чтобы объявить их, вместо того, чтобы говорить, что структуры не являются вещью на C++? Или у вас есть другие проблемы? – user2357112

ответ

157

Он возвращает true для обоих классов и структур. Я знаю, что в C++ они почти одно и то же, но я хотел бы знать, почему между ними нет различия в типе.

К сожалению, это распространенное заблуждение в C++. Иногда это происходит из-за фундаментального недоразумения, но в других случаях это происходит из-за двусмысленности на английском языке. Это может быть вызвано неточной диагностикой компилятора, плохо написанными книгами, неправильными SO-ответами и hellip;

Вы, наверное, читал что-то вроде этого:

«Там нет никакой разницы в C++ между структурой и классом, кроме видимости по умолчанию членов и база.»

Этот отрывок можно интерпретировать в том смысле, что это вводит в заблуждение, потому что понятия идентичности и равенства трудно отличить при использовании фразы типа «нет никакой разницы».

На самом деле, C++ не имеет структур с 1985 года. Он имеет классы.

Вид типов, которые вы объявляете с ключевым словом class и ключевым словом struct являются классами. Период. Ключевое слово struct и правила видимости, которые являются стандартными при определении класса с использованием этого ключевого слова, сохранялись только для обратной совместимости с C & hellip; но это синтаксис. Это не приводит к тому, что результирующие типы имеют другой тип.

Типичная черта не делает различий, потому что там буквально не одна.

+12

C++ имеет структуры, поскольку содержит C, который имеет структуры.Есть нулевые компиляторы C++, которые не принимают ключевое слово struct. Поэтому struct - это функция C++. Тот факт, что он получил его из C, недостаточно, чтобы заявить, что это не функция C++. Являются ли фигурные скобки не C++? –

+63

@WarrenP: [C++ не содержит «C] (http://stackoverflow.com/a/8594186/560648). Определение классов на C++ очень ясно. У C++ нет структур. Весь момент, который я делаю, заключается в том, что ключевое слово 'struct' создает классы, а не структуры. Ваше утверждение _ «поэтому struct - это функция C++», я боюсь. –

+2

Он реализует почти все средства C, включая все, что могут сделать структуры, а затем предоставляет средства? Итак, он содержит Struct, а struct - часть C++. Является структурой (при использовании в исходном файле на C++), которая не имеет методов-членов и используется, поскольку C-структура может использоваться, например, упакованное битовое поле, больше не является структурой, хотя она функционирует одинаково с C struct, когда используется для кодирования серии бит-полей? –

26

невозможно отличить разницу в семантике пустых определений, как

class C { 
public: 

}; 

из

struct S { 

}; 

или аналогично

class C { 

}; 

и

struct S { 
private: 

}; 

Помимо ключевого слова struct vs class, различия в поведении не обнаруживаются. См. Также this Q&A.

Примечание: Как заметил @KyleStrand, вывод также требует явных спецификаторов доступа, так и S : private Base {};C : Base {}; эквивалентны, так же, как и S : Base {};C : public Base {};, где S является структура, C является классом, и Base может быть или.

+2

Возможно, вы должны добавить что-то, указывающее (в соответствии с указанным вами ответом), что для полного семантического равенства struct/class спецификаторы доступа базового класса также должны быть явными, например. 'struct Derived: Base {' эквивалентно 'class Derived: public Base {public:' и 'class Derived: Base {' эквивалентно 'struct Derived: private Base {private:'. –

+1

Я думаю, вы неправильно поняли, что говорил @KyleStrand. Я думаю, он пытался сказать, что «класс C» наследует по умолчанию свои базы по умолчанию, а «struct S» публично наследует свои базы по умолчанию. Вы написали, что * подклассы * 'class C' private inherit * from * it по умолчанию и что подклассы' s S 'публично наследуют от него по умолчанию, а это не [http: // ideone.com/kyjV1C) [case] (http://ideone.com/DYHw3I). – user2357112

+0

@ user2357112 tnx, обновлено. – TemplateRex

22

Это то же самое. Единственная разница (видимость элементов по умолчанию) существует только во время компиляции. В противном случае нет никакой разницы между struct и class.

ETA: Что вы, возможно, хотите, это std::is_pod, в котором рассказывается, является ли ваш класс «обычным старым типом данных». Большая часть обсуждения и комментариев по этому вопросу, по-видимому, указывает на то, что именно те, кто считает, что это должно быть различие, действительно хотят.

+1

'bool isClass = std :: is_class :: value;' также оценивается во время компиляции. Должна быть проблема с оценкой 'std :: is_struct'. –

+1

Какая разница между ними? Какое преимущество оно может обеспечить? Вы не можете ничего сделать с тем, что вы не можете делать с другим. Это одно и то же. –

+0

@RobK Точкам было бы общение с другим языком или наложение регистров с отображением памяти с помощью структуры POD. –

13

Другие указали правильно, что в C++ ключевые слова struct и class имеют то же значение, за исключением различий в видимости элементов.

Независимо от того, называете ли вы совокупные типы, определенные таким образом «структуры» или «классы» или «weiruewzewiruz», зависит от вас. В интересах коммуникации, как правило, рекомендуется придерживаться установленных конвенций, поэтому я бы посоветовал «weiruewzewiruz».

Также рекомендуется использовать семантические различия в качестве ориентира для выбора слов. Использование struct более распространено для простых агрегированных данных, которые не имеют много внутренней логики и инвариантов; типичным применением будет struct point { float x; float y; };. Такие типы часто называют «структурами» или «структурами» в литературе. Не удивительно, если кто-то, использующий fprintf в C++, ссылался на первый аргумент как «указатель на структуру FILE». FILE является примером того, что означает Скотт Мейерс в „более эффективные C++“, пункт 34:

Безопасно предположить, что определение структуры, которая составляет в обоих языках [C и C++ -pas] уложен аналогичным образом оба компилятора.

Что касается естественного языка, выбор слова «структура» не случайна: Meyers говорит о простом старом агрегате данных, который имеет одинаковую семантику на обоих языках, вплоть до уровня бит.

Что касается языка программирования, не имеет значения, использовало ли в C++ определение совокупности данных ключевое слово struct или class (с указателем общего доступа). struct, пожалуй, более естественный выбор, поскольку семантика C++ совокупности является семантикой структуры C. Кроме того, использование struct позволяет как C, так и C++ источникам упростить совместное использование одного определения типа.

Стандарт C++ использует «структуру» и «структуру» как на естественном языке, так и на языке программирования не только в случаях совместимости: 1.7/5: «Структура, объявленная как», или 3.2/4 struct X; // declare X as a struct type. Самое интересное, 9/8, заложив основу для-критериев-взаимодействия:

8 Стандарт-макет структура представляет собой класс стандартного макета определяется класс-ключ или структура класса ключ класса. [...]

Как никто, кто читает это, может утверждать, что в C++ нет структур, которые находятся вне меня. Это явно не ошибка редактирования, поскольку термины «struct» и «class» явно заданы относительно друг друга.

Более интересные, чем выбор слов и вопросы вкуса, однако, являются явными, проверяемыми различиями. При каких обстоятельствах совокупность C++ сопоставима и совместима с C struct? Возможно, этот вопрос лежал в основе вашего вопроса? Стандартная компоновка, упомянутая в цитате, является критерием. Это подробно описано в 9/7 и в основном предусматривает, что

  • только один класс в иерархии наследования может иметь нестатические определения членов данных (возможно, потому, что стандарт не хочет, чтобы определить порядок элементов данных, определенный на различном уровни в такой иерархии);
  • не разрешены виртуальные или виртуальные базовые классы (из-за дополнительных данных экземпляра, необходимых для информации о времени выполнения);
  • все члены имеют тот же «контроль доступа» (открытый, защищенный или закрытый, вероятно, потому, что реализация может быть заказана путем контроля доступа).

Стандарт затем говорит

9 [Примечание: классы Standard верстки полезны для общения с кодом, написанным на других языках программирования. Их компоновка указана в 9.2.-концевой ноты]

Конечно определение структура, которая составляет в C удовлетворяет этим критериям, следовательно, утверждение Скотт Мейерс. FILE от stdio.h - выдающийся, не совсем тривиальный пример. Обратите внимание, что стандарт не гарантирует гарантии, поскольку макет объекта зависит от реализации и может изменяться только с помощью параметра компилятора.

Можно ли проверить класс стандартного макета с типом черты std::is_standard_layout<T>. Следующая программа, вдохновленная an example on cppreference, проверяет основные случаи, изложенные в стандарте.

#include <cstdio> 
#include <typeinfo> 
#include <type_traits> 

using namespace std; 

struct funcOnlyT // fine 
{ 
    int f(); 
}; 

class podT { // "class" is ok 
    int m1; 
    int m2; 
}; 

struct badAccessCtrlT { // bad: public/private 
    int m1; 
private: 
    int m2; 
}; 

struct polymorphicT { // bad: polymorphic 
    int m1; 
    int m2; 
    virtual void foo(); 
}; 


struct inheritOkT: podT // ok: inheritance, data only on one level 
{ 
    int f(); 
}; 


struct inheritPlusDataT: podT // bad: inheritance, data on 2 levels 
{ 
    int m3; 
}; 

template<typename T1, typename T2> 
struct templT  // ok with std layout types T1, T2 
{ 
    T1 m1; 
    T2 m2; 
}; 

// print type "name" and whether it's std layout 
template<typename T> 
void printIsStdLayout() 
{ 
    printf("%-20s: %s\n", 
      typeid(T).name(), 
      std::is_standard_layout<T>::value 
       ? "is std layout" 
       : "is NOT std layout"); 
} 

int main() 
{ 
    printIsStdLayout<funcOnlyT>(); 
    printIsStdLayout<podT>(); 
    printIsStdLayout<badAccessCtrlT>(); 
    printIsStdLayout<polymorphicT>(); 
    printIsStdLayout<inheritOkT>(); 
    printIsStdLayout<inheritPlusDataT>(); 
    printIsStdLayout<templT<int, float> >(); 
    printIsStdLayout<FILE>(); 
} 

Пример сеанса:

$ g++ -std=c++11 -Wall -o isstdlayout isstdlayout.cpp && ./isstdlayout 
9funcOnlyT   : is std layout 
4podT    : is std layout 
14badAccessCtrlT : is NOT std layout 
12polymorphicT  : is NOT std layout 
10inheritOkT  : is std layout 
16inheritPlusDataT : is NOT std layout 
6templTIifE   : is std layout 
9__sFILE64   : is std layout 
+1

Я был бы готов пойти на компромисс и согласиться с тем, что C++, с точки зрения стандартизации на прозу, которую вы цитируете, может иметь понятие «структуры», которое является подмножеством «классов». Однако по самому пропуску, который вы цитируете как 9/8, это не эквивалентно «набору типов, которые люди могут определить, используя ключевое слово« struct ». Я хотел бы пойти дальше и сказать, что эти предполагаемые стандартные значения «struct» не являются широко признанными или недвусмысленными для того, чтобы тип признака был назван после него. –

+0

@LightnessRacesinOrbit Re «Я был бы готов пойти на компромисс»: Пришло время. –

+0

Я прочел ваш ответ впервые прошлой ночью. Так, на самом деле, мне потребовалось около 4 минут. Является ли это приемлемым для вас, или вы хотели бы продолжать принимать участие в личной атаке без каких-либо причин? –

7
C++ 11 §9/8 ([класс]/8):

стандартная компоновка является стандартом класс -layout, определенный с помощью ключа класса struct или класс-ключclass. A стандарт-макет - класс стандартного макета, определенный с помощью ключа класса union.

C++ 11 §9/10 ([класс]/10):

СТРУЧОК структура не является объединением класса, который является как тривиальный класс, так и класс стандартного макета, и не имеет нестатических членов данных типа non-POD struct, non-POD union (или массив таких типов). [& Hellip;]

Поскольку POD структуры является классом стандартной компоновки это подмножество стандартной компоновки структуры. Насколько я знаю, это самый общий смысл struct в стандарте C++. И поэтому предположительно, что вы ищете, это черта типа или набор признаков типа, который позволяет идентифицировать структуру стандартного макета как таковой.

И вуаля, глядя на список черт характера is_class и is_standard_layout. Когда тип удовлетворяет ¹, а это “ struct ”. Или, точнее, это стандарт-макет struct, как определено в C++ 11 § 9/8.


Что касается

Я хотел бы знать, почему не проводится различие между [классом и структуры] в типе признака

Ну, есть. Это черта is_standard_layout.


Что касается

Всегда бесполезно, чтобы проверить эту разницу, или есть еще какая-то причина, что я не понимаю?

Нет, это не бесполезно проверять эту разницу. Стандарт определяет стандарт-макет по той причине, что он очень практичен. В качестве стандарта сам отмечает,

C++ 11 §9/9 ([класс]/9):

[Примечание: классы Стандарт-макета полезны для связи с кодом, написанным на других языках программирования. Их макет указан в 9.2.-end примечание]


Примечание:
¹ Указанное is_class черта верно для class или struct, но не для union, даже если стандарт определяет, что “ объединения является класс ”. То есть черта более специфична, чем общая терминология.

+2

Хотя вы делаете справедливый и интересный момент о стандартном определении «POD struct» (который я считаю редакционной проблемой, унаследованной от истории, но я не собираюсь утверждать, что здесь), я думаю, что разумно предположить, что это OP говорит о ключевых словах 'class' vs' struct'. Поэтому я предлагаю добавить к вашему ответу, что это определение «struct» - это не тот, на который OP ссылался (может быть). –

+0

@LightnessRacesinOrbit: Заметка, что, возможно, OP имела бессмысленную интерпретацию его слов, в уме, не помогло бы ИМХО. –

 Смежные вопросы

  • Нет связанных вопросов^_^