В каких сценариях лучше использовать struct против class в C++?
Я до сих пор не согласен - я подхожу к этому вопросу семантически. Возможно, есть какие-то технические отличия, но семантически их нет. Структуры действительно полезны для создания типов значений, классы - нет.
На практике кажется, что большинство людей используют class, если они планируют иметь функции-члены, и struct, если они этого не делают. Однако на самом деле это всего лишь условность. Структура и класс на самом деле в значительной степени идентичны, за исключением того, что для класса по умолчанию используется частный доступ, а для структуры по умолчанию используется открытый доступ.
Соглашения невероятно важны (учитывайте влияние категорий итераторов, средств защиты заголовков или пар файлов .cxx / .h). Этот ответ преуменьшает эту важность и поэтому менее полезен, чем большинство других.
Я бы не сказал, что мой комментарий «преуменьшает» важность условностей. Я думаю, что важно знать, что такое условности и что на самом деле является частью языка, если вы хотите быть больше, чем просто программистом-культом.
Я обнаружил, что редко использую структуры в C++, за исключением случаев, когда мне нужна автоматическая агрегатная инициализация Plain Old Data, я не думаю, что это можно сделать со структурами данных, определенными с помощью экземпляра класса.
Struct - для POD (простые старые данные) и доступ всех участников является общедоступным. Класс - когда вам нужна лучшая инкапсуляция и функции-члены для работы с состоянием класса.
Это верно только условно. Нет никакой разницы, кроме инкапсуляции по умолчанию.
@Dave - это соглашение - самая важная причина для этого. Если ему следовать последовательно, это единственное различие сразу же предоставит читателям много информации.
Я считаю, что для использования структур в C++ нет серьезных причин. Для меня структуры - это еще одна избыточная «особенность» C++, которая существует только для совместимости с C, например typedefs. Их бы не существовало, если бы C++ изначально не рассматривался как расширение C и разрабатывался с нуля, например, Java. В общем, я считаю, что многие из самых странных вещей в C++ связаны с совместимостью с C.
Вы на месте. Я лично считаю, что разработчики других языков позаимствовали эту идиому у разработчиков C++.
memset структура, vs memset класс.
@EvilTeach: memset a struct, vs memset a class. нет разницы в C++. Это зависит от того, является ли ваш memset POD-типом или нет.
Что произойдет, если это не POD?
@JasonBunting обратите внимание, что для C# это больше, чем «семантическая» разница. Структуры обрабатываются как значения и передаются по значению, а не по классам.
@Matthias - Мы приближаемся к 9 годам с тех пор, как я написал это, и кажется, что некоторые промежуточные комментарии были удалены. Тем не менее, я сказал: «Структуры действительно полезны для создания типов значений, классы - нет», и именно по той причине, которую вы упомянули.
Этот вопрос в некоторой степени актуален, что, если мы хотим добавить только конструкторы в структуры для инициализации данных.
@Kostas пишет: «[структур] не существовало бы, если бы C++ изначально не рассматривался как расширение C и разрабатывался с нуля, например, Java». Может быть, а может и нет. Я разработал систему ООП (на диалекте Лиспа), несовместимую с какой-либо существующей системой ООП, в которой классы называются «структурами». Они демонстрируют наследование, полиморфизм и все такое. Я легко мог бы использовать терминологию «класс». Таким образом, не факт, что при разработке с нуля, с чистого листа, будет использоваться «класс» вместо «структура».
IMO - это одна из (многих) областей боркаге от "C с классами" до C++. Классы с чистой статической диспетчеризацией и класс с чистой виртуальной диспетчеризацией - очень разные звери. С C++ мы получили неочевидную смесь, которая за эти годы сбила с толку многих программистов. Не гениально.





Различия между class и struct в C++:
struct и базовые классы / структуры по умолчанию являются public.class и базовые классы / стойки по умолчанию - private.И классы, и структуры могут иметь смесь членов public, protected и private, могут использовать наследование и могут иметь функции-члены.
Я бы порекомендовал вам:
struct для простых структур данных без каких-либо классовых функций;class, когда вы используете такие функции, как члены private или protected, нестандартные конструкторы и операторы и т. д.Структура без модификаторов или методов называется структурой POD, которая существует как обратно совместимый интерфейс с библиотеками C, поскольку (предположительно) гарантированно размещается, как если бы это была структура C. Однако, за исключением этого единственного исключения, единственная разница заключается в том, как указано.
@ workmad3: Название вводит в заблуждение, но 9/4 (C++ 03) говорит: «POD-структура - это совокупный класс, который не имеет нестатических элементов данных типа non-POD-struct, non-POD-union. (или массив таких типов) или ссылку и не имеет определяемого пользователем оператора присваивания копии и определенного пользователем деструктора. " Нет ограничений на использование ключа класса "struct" и нет ограничений на использование "public" (см. 8.5.1 / 1 для агрегированных требований). Это не разница между «структурой» и «классом».
Ваше использование термина «совокупность» может быть неправильно понято, учитывая определение стандарта. :)
Согласно книге Страуструпа «Принципы и практика»: «структуры должны в первую очередь использоваться там, где члены могут принимать любое значение» (т.е. там, где нельзя определить значимый инвариант класса)
Важная вещь о структуре POD заключается в том, что она ведет себя идентично той же структуре в компиляторе C, поэтому, если вы сделали странные предположения в своем коде C, например, возможность использовать последовательные члены memcpy, эти предположения не нарушаются, когда вы используете те же код на C++. Очевидно, что класс никогда не будет вести себя так, как в компиляторе C (потому что в C он не компилируется).
Конечно, вы можете использовать классы при взаимодействии с C. Нет никакой разницы между классами и структурами. Структуры - это классы; только доступ по умолчанию переключается с частного на публичный.
То же самое относится и к наследованию по умолчанию. По этой причине я бы предпочел структуры: публичное наследование (is-a) гораздо более распространено, чем частное наследование (is-implementation-in-terms-of).
«Я бы рекомендовал использовать структуры как простые старые структуры данных ...». Почему? Есть ли преимущество в использовании структур перед классами (когда вам не нужно беспокоиться о совместимости с C)?
Книга Бьярна Страуструпа "Язык программирования C++", 4-е издание, авторское право 2013 г., стр. 48: [Struct] Having the data specified separately from the operations on it has advantages, such as the ability to use the data in arbitrary ways. [Class] However, a tighter connection between the representation and the operations is needed for a user-defined type to have all the properties expected of a "real type."
какая техническая необходимость даже в частных членах? все работает нормально, если они все публичные, верно? просто ли программисту просто организовать и понять, какие переменные не будут использоваться где-либо еще? что на самом деле физически меняется код, когда что-то частное или публичное?
@Puddle Это влияет на макет (stackoverflow.com/q/15763091/560648), но в остальном нет. Это инструмент программиста, который не влияет на смысл программы. Создание хорошо спроектированного класса, который не позволяет внешним факторам изменять переменные private, упрощает поддержку инвариантов в вашем классе и, таким образом, доказывает правильность вашей программы. tl; dr: иначе слишком легко создавать ошибки
@ mellow-yellow К сожалению (но не так уж необычно), что кто-то из потенциальных авторитетов Бьярна продолжает торговать такими неудачными вариантами терминологии. Согласно стандартам своего собственного языка, он искажает различие! Если предположить, что это была дословная цитата.
Что такое классовые функции
@Voyager все, что служит для ООП, например, функции-члены и наследование.
Я знаю, что вы можете объявить структуру упакованной, но я не знаю, можете ли вы упаковать класс C++ ... Значит, выравнивание - это тоже разница.
Для C++ действительно нет большой разницы между структурами и классами. Основное функциональное отличие состоит в том, что члены структуры по умолчанию являются общедоступными, а в классах по умолчанию - частными. В остальном, что касается языка, они эквивалентны.
Тем не менее, я обычно использую структуры в C++, как и в C#, аналогично тому, что сказал Брайан. Структуры - это простые контейнеры данных, в то время как классы используются для объектов, которым необходимо воздействовать на данные в дополнение к тому, чтобы просто удерживать их.
Это почти одно и то же. Благодаря магии C++ структура может содержать функции, использовать наследование, создавать с использованием «нового» и т. д. Точно так же, как класс.
Единственное функциональное отличие состоит в том, что класс начинается с частных прав доступа, а структура начинается с публичных. Это поддержка обратной совместимости с C.
На практике я всегда использовал структуры как держатели данных и классы как объекты.
Одно место, где структура была для меня полезной, - это когда у меня есть система, которая получает сообщения фиксированного формата (скажем, через последовательный порт) от другой системы. Вы можете преобразовать поток байтов в структуру, которая определяет ваши поля, а затем легко получить к ним доступ.
typedef struct
{
int messageId;
int messageCounter;
int messageData;
} tMessageType;
void processMessage(unsigned char *rawMessage)
{
tMessageType *messageFields = (tMessageType *)rawMessage;
printf("MessageId is %d\n", messageFields->messageId);
}
Очевидно, это то же самое, что и в C, но я считаю, что накладные расходы, связанные с необходимостью декодирования сообщения в класс, обычно того не стоят.
То же самое может быть достигнуто в C.
Или вы можете просто реализовать operator >> в классе вместо написания функции processMessage, что сделает ваш C++ больше похожим на правильный C++, а не на C.
Помимо того факта, что он не переносится между разными системами, это нарушает правила псевдонима, поэтому не гарантируется его работа даже в рамках одной архитектуры.
@underscore_d Это может работать независимо от платформы (но не от компилятора), но вы должны использовать фиксированные битовые поля, структуру __packed__ и иметь реализацию ifdef, учитывающую порядок байтов (вам нужно изменить порядок на машине, где порядок байтов противоположен внешним данным источник предоставляет). Это некрасиво, но я привык упаковывать / распаковывать регистры для удаленных периферийных устройств на встроенных платформах портативным способом.
@crasic Но это не совсем портативный вариант, не так ли? После того, как вы приложили все усилия, чтобы запереться в одной такой реализации, действительно ли вы чувствуете, что для распаковки это было быстрее, чем просто написать совместимый со стандартами код? Серьезный вопрос. Я приложил немало усилий, чтобы написать такой код сам, и в конечном итоге это было не слишком сложно и было очень познавательно.
@underscore_d Достаточно портативен на время существования проекта или кодовой базы для встраиваемой системы, и ADC не меняет свой набор регистров в течение 30 лет. Он выполняет свою работу, свой единственный цикл и легко тестируется, и его можно передать драйверам ядра, системным вызовам void* и передать между C и C++, я говорю беспроигрышно?
@underscore_d Разве правила сглаживания не применяются только к аргументам функции, не являющейся символом?
@jacwah Да, хорошее замечание. Псевдонимы здесь не будут проблемой, потому что один из указателей - это тип char, который не подвержен псевдониму. Тем не менее, все еще существует проблема, хотя и другая: приведение char* к другому типу, если на самом деле не было никакого объекта последнего типа, уже инициализированного по этому адресу, - это UB, поскольку это нарушает правила времени жизни. Afaik, даже если целевой тип легко конструируемый, просто выделенной памяти недостаточно для C++, чтобы формально разрешить обработку этой памяти как этого типа.
Чтобы ответить на мой собственный вопрос (бесстыдно), как уже упоминалось, привилегии доступа - единственное различие между ними в C++.
Я обычно использую структуру только для хранения данных. Я позволю ему получить несколько вспомогательных функций, если это упростит работу с данными. Однако как только данные потребуют управления потоком (т.е. геттеры / сеттеры, которые поддерживают или защищают внутреннее состояние) или начнут получать какие-либо основные функции (в основном более объектно-подобные), они будут «обновлены» до класса, чтобы лучше сообщать о намерениях.
Структуры (POD, в более общем смысле) удобны, когда вы предоставляете C-совместимый интерфейс с реализацией C++, поскольку они переносятся через языковые границы и форматы компоновщика.
Если вас это не беспокоит, то я полагаю, что использование «структуры» вместо «класса» является хорошим средством передачи намерений (как @ZeroSignal сказал выше). Структуры также имеют более предсказуемую семантику копирования, поэтому они полезны для данных, которые вы собираетесь записать на внешний носитель или отправить по сети.
Структуры также удобны для различных задач метапрограммирования, таких как шаблоны признаков, которые просто предоставляют кучу зависимых определений типов:
template <typename T> struct type_traits {
typedef T type;
typedef T::iterator_type iterator_type;
...
};
... Но на самом деле это просто использование общедоступного уровня защиты структуры по умолчанию ...
Это неправильное использование POD. Структура (или класс) может быть структурой POD, если (и только если) она содержит ТОЛЬКО члены POD.
«предсказуемая семантика копирования»: симантика такая же, как и для класса (и имеет те же проблемы (неглубокая копия)).
Этот пост заставит вас поверить (надеюсь, случайно), что все структуры являются POD. Это совсем не так. Надеюсь, это не вводит людей в заблуждение.
Я никогда не использую "struct" в C++.
Я не могу представить себе сценарий, в котором вы использовали бы структуру, когда вам нужны частные члены, если только вы не пытаетесь умышленно запутать.
Кажется, что использование структур является скорее синтаксическим указанием того, как будут использоваться данные, но я бы предпочел просто создать класс и попытаться сделать это явным в имени класса или с помощью комментариев.
Например.
class PublicInputData {
//data members
};
По моему мнению, «синтаксическое указание на то, как будут использоваться данные» - прекрасная причина для использования структуры, особенно если альтернативой является использование комментария или имени в имени класса.
Разве объявление struct не будет довольно явным, что члены класса по умолчанию будут общедоступными?
Единственный раз, когда я использую структуру вместо класса, - это когда я объявляю функтор непосредственно перед его использованием в вызове функции и хочу минимизировать синтаксис для ясности. например.:
struct Compare { bool operator() { ... } };
std::sort(collection.begin(), collection.end(), Compare());
Теперь, когда прошло несколько лет, и C++ 11 поддерживается всеми основными компиляторами, Лямбды делают это еще более кратким.
они одно и то же с разными значениями по умолчанию (частные по умолчанию для class и общедоступные по умолчанию для struct), поэтому теоретически они полностью взаимозаменяемы.
Итак, если я просто хочу упаковать некоторую информацию для перемещения, я использую структуру, даже если я помещаю туда несколько методов (но не много). Если это в основном непрозрачная вещь, где основное использование будет через методы, а не напрямую с элементами данных, я использую полный класс.
Структуры по умолчанию имеют общий доступ, а классы по умолчанию имеют частный доступ.
Лично я использую структуры для объектов передачи данных или как объекты-значения. При использовании в таком качестве я объявляю все члены как константы, чтобы предотвратить изменение другим кодом.
Как отмечают все остальные, на самом деле существует только два фактических языковых различия:
struct по умолчанию имеет открытый доступ, а class - частный доступ.struct по умолчанию использует наследование public, а class - наследование private. (По иронии судьбы, как и во многих других случаях в C++, по умолчанию используется обратное: наследование public является гораздо более распространенным выбором, но люди редко объявляют struct, просто чтобы сэкономить на вводе ключевого слова «public».Но реальная разница на практике заключается между class / struct, который объявляет конструктор / деструктор, и тем, который не объявляет. Существуют определенные гарантии для типа POD «простые старые данные», которые больше не применяются, когда вы берете на себя создание класса. Чтобы сохранить это различие, многие люди намеренно используют только struct для типов POD, а если они собираются добавлять какие-либо методы вообще, используют class. В остальном разница между двумя приведенными ниже фрагментами бессмысленна:
class X
{
public:
// ...
};
struct X
{
// ...
};
(Кстати, вот ветка с хорошими объяснениями того, что на самом деле означает «тип POD»: Что такое типы POD в C++?)
Хороший пример, касающийся различий наследования: здесь.
Независимо от того, используете ли вы struct или class, не имеет отношения к тому, является ли ваш объект POD или вам следует определить конструктор / деструктор копирования. Функции-члены также не имеют отношения к чему-то, что является POD. Когда я перечитываю то, что вы написали, я вижу, что вы не предлагаете другого, но текущая формулировка сбивает с толку
@DavidStone В принципе, структуры POD должны быть гарантированно обратно совместимы с кодом C, и, таким образом, в основном предполагается, что они просто спроектированы как структуры в стиле C.
@juanchopanza, как так? Есть ли еще какие-нибудь отличия, о которых вы знаете?
@rdelfin Я думаю, что неправильно прочитал абзац, потому что вопрос заключается в различиях между struct и class, а когда дело доходит до компоновки объектов, их нет. POD также немного изменился после C++ 11. Тем не менее, пункты списка правильные. когда вы используете любое ключевое слово для определения класса, речь идет только о значениях по умолчанию.
Из C++ FAQ Lite:
The members and base classes of a struct are public by default, while in class, they default to private. Note: you should make your base classes explicitly public, private, or protected, rather than relying on the defaults.
struct and class are otherwise functionally equivalent.
OK, enough of that squeaky clean techno talk. Emotionally, most developers make a strong distinction between a class and a struct. A struct simply feels like an open pile of bits with very little in the way of encapsulation or functionality. A class feels like a living and responsible member of society with intelligent services, a strong encapsulation barrier, and a well defined interface. Since that's the connotation most people already have, you should probably use the struct keyword if you have a class that has very few methods and has public data (such things do exist in well designed systems!), but otherwise you should probably use the class keyword.
Я не понимаю, почему они заявляют, что структура и класс функционально одинаковы, но говорят, что в некоторых случаях предпочитают одно над другим без каких-либо объяснений.
Причина в условности. Компилятору все равно, какой из них вы используете, но другому разработчику, просматривающему ваш код, будет легче понять, что вы имели в виду.
@deetz: Весь третий абзац - это рассуждения.
Вау, я из «старой школы» понятия не имел, что у структуры могут быть методы и даже наследование. Я всегда использовал struct for при использовании только данных без методов и обычно при работе с кодом API, которому нужна структура. Могут ли структуры также поддерживать множественное наследование?
Я думал, что Structs задумывались как структура данных (например, массив информации с несколькими типами данных), а классы предназначались для упаковки кода (например, коллекции подпрограмм и функций).
:(
Я использую структуру только тогда, когда мне нужно хранить некоторые данные без каких-либо связанных с ними функций-членов (для работы с данными-членами) и для прямого доступа к переменным данных.
Например: чтение / запись данных из файлов и потоков сокетов и т. д. Передача аргументов функции в структуре, где аргументов функции слишком много, а синтаксис функции выглядит слишком длинным.
Технически нет большой разницы между классом и структурой, кроме доступности по умолчанию. Более того, это зависит от стиля программирования, как вы его используете.
Технически оба они одинаковы в C++ - например, структура может иметь перегруженные операторы и т. д.
Тем не мение :
Я использую структуры, когда хочу передавать информацию нескольких типов одновременно Я использую классы, когда имею дело с «функциональным» объектом.
Надеюсь, это поможет.
#include <string>
#include <map>
using namespace std;
struct student
{
int age;
string name;
map<string, int> grades
};
class ClassRoom
{
typedef map<string, student> student_map;
public :
student getStudentByName(string name) const
{ student_map::const_iterator m_it = students.find(name); return m_it->second; }
private :
student_map students;
};
Например, я возвращаю структуру student в методах get ... () здесь - наслаждайтесь.
Как все говорят, единственная реальная разница - это доступ по умолчанию. Но я особенно использую структуры, когда мне не нужна какая-либо инкапсуляция с простым классом данных, даже если я реализую некоторые вспомогательные методы. Например, когда мне нужно что-то вроде этого:
struct myvec {
int x;
int y;
int z;
int length() {return x+y+z;}
};
+1 за пример структуры с некоторыми функциями-членами, которые не чувствуют, что вы «убрали структурированность».
When would you choose to use struct and when to use class in C++?
Я использую struct, когда определяю functors и POD. В противном случае я использую class.
// '()' is public by default!
struct mycompare : public std::binary_function<int, int, bool>
{
bool operator()(int first, int second)
{ return first < second; }
};
class mycompare : public std::binary_function<int, int, bool>
{
public:
bool operator()(int first, int second)
{ return first < second; }
};
Этот ответ показывает признаки возраста :) std::binary_function<> не просто устарел, C++ 17 даже удаляет его.
На самом деле это не удивительно, поскольку он был написан во времена C++ 03, языка, определенного 15 лет назад.
Вы можете использовать «struct» в C++, если вы пишете библиотеку, внутренняя часть которой - C++, но API может вызываться кодом C или C++. Вы просто создаете один заголовок, содержащий структуры и глобальные функции API, которые вы предоставляете как для кода C, так и для кода C++ следующим образом:
// C access Header to a C++ library
#ifdef __cpp
extern "C" {
#endif
// Put your C struct's here
struct foo
{
...
};
// NOTE: the typedef is used because C does not automatically generate
// a typedef with the same name as a struct like C++.
typedef struct foo foo;
// Put your C API functions here
void bar(foo *fun);
#ifdef __cpp
}
#endif
Затем вы можете написать функциональную панель () в файле C++, используя код C++, и сделать его вызываемым из C, и два мира могут обмениваться данными через объявленную структуру. Конечно, есть и другие предостережения при смешивании C и C++, но это упрощенный пример.
Самый подходящий ответ. C-совместимость - действительно самая важная причина. все остальные вещи, такие как доступ по умолчанию, являются эзотерическими.
В существующих ответах много заблуждений.
И class, и struct объявляют класс.
Да, возможно, вам придется изменить порядок ключевых слов для изменения доступа внутри определения класса, в зависимости от того, какое ключевое слово вы использовали для объявления класса.
Но, помимо синтаксиса, причиной выбора Только одного из них является соглашение / стиль / предпочтение.
Некоторым людям нравится использовать ключевое слово struct для классов без функций-членов, потому что полученное определение «выглядит» как простая структура из C.
Точно так же некоторые люди любят использовать ключевое слово class для классов с функциями-членами и данными private, потому что в нем написано «класс» и поэтому выглядит как примеры из их любимой книги по объектно-ориентированному программированию.
Реальность такова, что это полностью зависит от вас и вашей команды, и это не будет иметь никакого значения для вашей программы.
Следующие два класса абсолютно эквивалентны во всех отношениях, кроме названия:
struct Foo
{
int x;
};
class Bar
{
public:
int x;
};
Вы даже можете переключать ключевые слова при повторном объявлении:
class Foo;
struct Bar;
(хотя это нарушает сборки Visual Studio из-за несоответствия, поэтому компилятор выдаст предупреждение, когда вы это сделаете.)
и оба следующих выражения имеют значение true:
std::is_class<Foo>::value
std::is_class<Bar>::value
Однако обратите внимание, что вы не можете переключать ключевые слова, когда переопределение; это только потому, что (согласно правилу одного определения) повторяющиеся определения классов в единицах трансляции должны быть "состоят из одинаковой последовательности токенов". Это означает, что вы даже не можете обменять const int member; на int const member;, и это не имеет ничего общего с семантикой class или struct.
Это был очень информативный и, честно говоря, мой любимый ответ. Все остальные относятся к ним как к отдельным объектам, тогда как под капотом они одинаковы. Интересно, считается ли определение структуры в среде Arduino классом cpp, поскольку оно скомпилировано с использованием g ++.
@Ben Конечно, это так. Компилятор Arduino компилирует C++; это конец.
Итак, если я правильно понимаю: пока ваши модификаторы видимости явные, а не опущенные, это не имеет значения. Вы можете написать огромное приложение на C++, используя только структуры; или вы можете пройти и изменить каждый случай структуры на класс. Пока вы не используете видимость по умолчанию, приложения будут точно такими же.
Я не уверен, что одна единица трансляции программы на C++ может иметь полное объявление class foo { public: ... };, а другая - struct foo { ... };, что должно выполняться согласно «абсолютно эквивалентному» утверждению. Дело в том, что неполные объявления struct foo; и class foo; взаимозаменяемы. Они не определяют тело класса и поэтому ничего не говорят с макетом доступа.
@Kaz: Вы правы - если определения были буквально для одного и того же типа, они должны быть лексически идентичными, чтобы поведение было четко определено. структурный ключ и ключ класса в остальном логически взаимозаменяемы (где семантика не затрагивается), а Foo и Bar по-прежнему являются эквивалентными / идентичными типами. Я обязательно сказал «когда переобъявление» и привел пример. Если подумать, я поясню это в ответе, чтобы не вводить людей в заблуждение в UB.
Ваши два ответа используют друг друга как источник. Почему?
Я использую структуры, когда мне нужно создать тип или функтор POD.
Члены класса по умолчанию являются закрытыми.
class test_one {
int main_one();
};
Эквивалентно
class test_one {
private:
int main_one();
};
Итак, если вы попробуете
int two = one.main_one();
Мы получим ошибку: main_one is private, потому что он недоступен. Мы можем
решить его, инициализировав его, указав его общедоступный, т.е.
class test_one {
public:
int main_one();
};
Структура - это класс, члены которого по умолчанию являются общедоступными.
struct test_one {
int main_one;
};
Означает, что main_one является частным, т.е.
class test_one {
public:
int main_one;
};
Я использую структуры для структур данных, где члены могут принимать любое значение, это так проще.
Преимущество struct перед class состоит в том, что он сохраняет одну строку кода, если придерживается принципа «сначала публичные члены, затем частные». В этом свете я считаю ключевое слово class бесполезным.
Вот еще одна причина использовать только struct, а не class. Некоторые рекомендации по стилю кода для C++ предлагают использовать строчные буквы для макросов функций, обосновывая это тем, что при преобразовании макроса во встроенную функцию менять имя не нужно. То же самое. У вас есть хорошая структура в стиле C, и однажды вы обнаружите, что вам нужно добавить конструктор или какой-нибудь удобный метод. Вы меняете его на class? Повсюду?
Различать structs и classes - это слишком хлопотно, мешать делать то, что мы должны делать - программировать. Как и многие другие проблемы C++, она возникает из-за сильного стремления к обратной совместимости.
Зачем вам нужно менять его на class? Вы думали, что класс, определенный с помощью ключевого слова struct, не может иметь функций-членов или конструктора?
@LightnessRacesinOrbit из-за 1. согласованности и 2. некоторых статических анализаторов жалуется на нарушение 1.
Этого не следует. Каких еще «последовательностей» вы придерживаетесь? Каждый класс с членом joe() должен быть определен с ключевым словом class? Каждый класс с минимум 4 членами int должен быть определен с ключевым словом struct?
@LightnessRacesinOrbit Я имею в виду идиому «агрегаты POD определены с помощью struct, агрегаты с методами определены с помощью class». Слишком много хлопот.
Как указывали другие
Есть четкая рекомендация о том, когда использовать это от Страуструпа / Саттера:
Use class if the class has an invariant; use struct if the data members can vary independently
Однако имейте в виду, что пересылать объявление sth неразумно. как класс (class X;) и определите его как структуру (struct X { ... }).
Он может работать с некоторыми компоновщиками (например, g ++) и может не работать с другими (например, MSVC), так что вы окажетесь в аду разработчиков.
Вы можете описать эти проблемы компоновщика?
@LightnessRacesinOrbit К сожалению, я не могу. Я даже не могу придумать пример. Тривиальный class Foo; struct Foo { void bar() {} }; int main() { Foo().bar(); } не только компилируется и работает с MSVC 2017, но и выдает четкое предупреждение о том, что Foo был объявлен как struct, но определен как class. Но я также хорошо помню, что поиск этой глупой ошибки стоил нашей команде полдня. Я не уверен, какую версию MSVC мы использовали тогда.
Компоновщик не должен даже знать о том, использовали ли вы class или struct в прямом объявлении, и оба они свободно взаимозаменяемы в соответствии со стандартом (хотя известно, что VS предупреждает; я всегда предполагал, что это было сделано только для того, чтобы избежать очевидных ошибок программиста). Здесь что-то не пахнет. Вы уверены, что это не ошибка нарушения ODR?
Хм, кажется, VS не соответствует требованиям в этом отношении (иди разберись)
Точно не помню. Проблема возникла не в приложении напрямую, а в библиотеке, которая использовалась в gtest. Я просто знаю, что компоновщик выдавал непонятные ошибки (LNK ???). Как только я заменил struct-форварды на class-форварды, проблемы исчезли. На сегодняшний день я тоже нахожу это странным. Я был бы рад, если бы вы могли пролить на это немного света.
Нажмите на ссылку, которую я дал
Все члены класса по умолчанию являются закрытыми, а все члены структуры по умолчанию являются общедоступными. Класс имеет частные базы по умолчанию, а Struct имеет общедоступные базы по умолчанию. Struct в случае C не может иметь функции-члены, тогда как, как и в случае C++, мы можем добавлять функции-члены в структуру. Кроме этих различий, я не нахожу в них ничего удивительного.
И struct, и class одинаковы внутри, хотя с разными значениями по умолчанию в отношении видимости, struct по умолчанию является общедоступным, а class по умолчанию - частным. Вы можете заменить один из них другим с соответствующим использованием private и public. Оба они позволяют наследование, методы, конструкторы, деструкторы и все остальные преимущества объектно-ориентированного языка.
Однако одно огромное различие между ними заключается в том, что struct как ключевое слово поддерживается в C, а class - нет. Это означает, что можно использовать struct во включаемом файле, который может быть #include как в C++, так и в C, при условии, что struct представляет собой простой стиль C struct, а все остальное во включаемом файле совместимо с C, т.е. как private, public, без методов, без наследования и т. д. и т. д.
struct в стиле C может использоваться с другими интерфейсами, которые поддерживают использование struct в стиле C для передачи данных по интерфейсу и обратно.
struct в стиле C - это своего рода шаблон (не шаблон C++, а скорее шаблон или трафарет), который описывает структуру области памяти. За прошедшие годы были созданы интерфейсы, которые можно использовать с C и с подключаемыми модулями C (здесь мы видим Java, Python и Visual Basic), некоторые из которых работают со стилем C. struct.
Этот ответ противоречит сам себе: они «внутри одинаковы», но есть «одна огромная разница». Хм? Если реализация C++ обрабатывает структуру специально для сохранения совместимости, как описано, тогда они обязательно являются нет одинаковыми «под капотом». Остальная часть описания ясна и совместима с другими ответами и комментариями, но если есть разница, просто объясните это напрямую, не отступая от открывающего объявления. По крайней мере, предоставьте правильный контекст для первого предложения, такого как «Если какой-либо тип используется полностью в контексте C++, то ...»
Просто чтобы решить эту проблему с точки зрения C++ 20 Standardese (работает с N4860) ...
учебный класс - это тип. Ключевые слова class и struct (и union) - в грамматике C++ - ключ класса, и единственное функциональное значение выбора class или struct:
The class-key determines whether ... access is public or private by default (11.9).
То, что ключевое слово class приводит к членам по умолчанию private, а ключевое слово struct приводит к членам по умолчанию public, документировано в примерах в 11.9.1:
class X { int a; // X::a is private by default: class used
...против...
struct S { int a; // S::a is public by default: struct used
1.9 также говорит:
In the absence of an access-specifier for a base class,
publicis assumed when the derived class is defined with the class-keystructandprivateis assumed when the class is defined with the class-keyclass.
Есть требование:
In a redeclaration, partial specialization, explicit specialization or explicit instantiation of a class template, the class-key shall agree in kind with the original class template declaration (9.2.8.3).
...in any elaborated-type-specifier, the
enumkeyword shall be used to refer to an enumeration (9.7.1), theunionclass-key shall be used to refer to aunion(11.5), and either theclassorstructclass-key shall be used to refer to a non-union class (11.1).
Предоставляется следующий пример (когда требуется согласованность нет):
struct S { } s; class S* p = &s; // OK
Тем не менее, некоторые компиляторы могут об этом предупреждать.
Интересно, что в то время как типы, которые вы создаете с помощью struct, class и union, называются «классами», у нас есть ...
A standard-layout struct is a standard layout class defined with the class-key
structor the class-keyclass.
... так что на стандартном языке, когда говорят о структура стандартного макета, он использует "struct", чтобы подразумевать "не объединение".
Мне любопытно, есть ли подобное использование «структуры» в другой терминологии, но это слишком большая работа, чтобы проводить исчерпывающий поиск в Стандарте. Комментарии по этому поводу приветствуются.
Это применимо не только к C++, но и к любому языку, который предоставляет как структуры, так и классы.