Когда вы должны использовать класс против структуры в C++?

В каких сценариях лучше использовать struct против class в С ++?

28 ответов

Решение

Различия между class и struct в C++ это то, что структуры имеют по умолчанию public члены и базы и классы имеют по умолчанию private члены и базы. Оба класса и структуры могут иметь смесь public, protected а также private члены, могут использовать наследование и могут иметь функции-члены.

Я бы порекомендовал использовать структуры в качестве простых старых структур данных без каких-либо классоподобных функций и использовать классы в качестве совокупных структур данных с private данные и функции-члены.

Как все остальные отмечают, на самом деле есть только два фактических языковых различия:

  • struct по умолчанию для публичного доступа и class по умолчанию для частного доступа.
  • При наследовании struct по умолчанию public наследование и class по умолчанию private наследование. (Как ни странно, как и во многих других вещах в C++, по умолчанию задом наперед: public Наследование является гораздо более распространенным выбором, но люди редко заявляют structпросто, чтобы сэкономить на наборе "public"ключевое слово.

Но реальная разница на практике между class/struct который объявляет конструктор / деструктор и тот, который этого не делает. Существуют определенные гарантии для типа POD "обычные старые данные", которые больше не применяются, когда вы берете на себя конструкцию класса. Чтобы сохранить это различие, многие люди сознательно используют только structs для типов POD, и, если они собираются добавить какие-либо методы вообще, используйте classэс. Разница между двумя фрагментами ниже бессмысленна:

class X
{
  public:

  // ...
};

struct X
{
  // ...
};

(Кстати, вот поток с некоторыми хорошими объяснениями о том, что на самом деле означает "тип POD": что такое типы POD в C++?)

Есть много заблуждений в существующих ответах.

И то и другое class а также struct объявить класс.

Да, вам, возможно, придется изменить ваши ключевые слова, изменяющие доступ, внутри определения класса, в зависимости от того, какое ключевое слово вы использовали для объявления класса.

Но, помимо синтаксиса, единственной причиной выбора одного из них является соглашение / стиль / предпочтение.

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

Точно так же некоторым людям нравится использовать class ключевое слово для классов с функциями-членами и private данные, потому что там написано "класс", и поэтому они выглядят как примеры из их любимой книги по объектно-ориентированному программированию.

Реальность такова, что это полностью зависит от вас и вашей команды, и это не будет буквально никакой разницы для вашей программы.

Следующие два класса абсолютно эквивалентны во всех отношениях, кроме их имени:

struct Foo
{
   int x;
};

class Bar
{
public:
   int x;
};

Вы даже можете переключать ключевые слова при повторном выделении:

class Foo;
struct Bar;

(хотя некоторые компиляторы выдают предупреждение, когда вы делаете это, исходя из предположения, что вы, вероятно, не собирались делать что-то настолько запутанное, и поэтому вам нужно будет дважды проверить ваш код.)

и следующие выражения оба имеют значение true:

std::is_class<Foo>::value
std::is_class<Bar>::value

Обратите внимание, что вы не можете переключать ключевые слова при переопределении; это только потому, что (согласно правилу одного определения) повторяющиеся определения классов в единицах перевода должны "состоять из одной и той же последовательности токенов". Это означает, что вы не можете даже обменять const int member; с int const member; и не имеет ничего общего с семантикой class или же struct,

Единственный раз, когда я использую структуру вместо класса, это когда объявляю функтор непосредственно перед его использованием в вызове функции и хочу свести к минимуму синтаксис для ясности. например:

struct Compare { bool operator() { ... } };
std::sort(collection.begin(), collection.end(), Compare()); 

Из C++ FAQ Lite:

Члены и базовые классы структуры являются открытыми по умолчанию, а в классе они по умолчанию являются закрытыми. Примечание: вы должны сделать свои базовые классы явно общедоступными, закрытыми или защищенными, а не полагаться на значения по умолчанию.

Структура и класс в остальном функционально эквивалентны.

Ладно, хватит этого скрипучего чистого техно разговора. Эмоционально большинство разработчиков проводят четкое различие между классом и структурой. Структура просто ощущается как открытая куча битов с очень небольшим количеством способов инкапсуляции или функциональности. Класс чувствует себя живым и ответственным членом общества с интеллектуальными услугами, сильным барьером инкапсуляции и четко определенным интерфейсом. Поскольку это значение имеет большинство людей, вам, вероятно, следует использовать ключевое слово struct, если у вас есть класс, у которого очень мало методов и открытых данных (такие вещи существуют в хорошо спроектированных системах!), Но в противном случае вам, вероятно, следует использовать класс ключевое слово.

Вы можете использовать "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

Затем вы можете написать функцию bar() в файле 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, но я обнаружил, что накладные расходы, связанные с декодированием сообщения в класс, обычно не стоят того.

Как говорят все, единственная реальная разница - доступ по умолчанию. Но я особенно использую struct, когда я не хочу никакой инкапсуляции с простым классом данных, даже если я реализую некоторые вспомогательные методы. Например, когда мне нужно что-то вроде этого:

struct myvec {
    int x;
    int y;
    int z;

    int length() {return x+y+z;}
};

Чтобы ответить на мой собственный вопрос (беззастенчиво), как уже упоминалось, привилегии доступа - единственное различие между ними в C++.

Я склонен использовать структуру только для хранения данных. Я позволю ему получить несколько вспомогательных функций, если это облегчит работу с данными. Однако, как только данные требуют управления потоком (т. Е. Методы получения / установки, которые поддерживают или защищают внутреннее состояние) или начинают приобретать какие-либо основные функциональные возможности (в основном более объектоподобные), они будут "обновлены" до класса, чтобы лучше передавать намерения.

Структуры ( PODs, в более общем смысле) удобны, когда вы предоставляете C-совместимый интерфейс с реализацией C++, поскольку они переносимы через языковые границы и форматы компоновщиков.

Если это вас не касается, то я полагаю, что использование "struct" вместо "class" является хорошим средством передачи намерений (как сказано выше в @ZeroSignal). Структуры также имеют более предсказуемую семантику копирования, поэтому они полезны для данных, которые вы собираетесь записывать на внешний носитель или передавать по проводам.

Структуры также удобны для различных задач метапрограммирования, таких как шаблоны признаков, которые просто предоставляют набор зависимых типов:

template <typename T> struct type_traits {
  typedef T type;
  typedef T::iterator_type iterator_type;
  ...
};

... Но это на самом деле просто использование общедоступного уровня защиты struct по умолчанию...

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

Тем не менее, я склонен использовать структуры в C++, как я делаю в C#, подобно тому, что сказал Брайан. Структуры - это простые контейнеры данных, в то время как классы используются для объектов, которые должны воздействовать на данные в дополнение к их удержанию.

Я бы порекомендовал не смешивать struct с и class эс.

Как уже отмечали другие

  • оба эквивалентны, кроме видимости по умолчанию
  • Могут быть причины, по которым необходимо использовать один или другой по любой причине

Если вы не вынуждены, идти только с struct или только class Потому что он защищает вас от проблем с компоновщиками с нулевыми затратами.

Если вы перешлите объявить что-н. лайк class X; а позже определите это как struct X { ... } он может работать на некоторых компоновщиках (например, g++) и может не работать на других (например, MSVC), так что вы окажетесь в аду разработчиков. Как нет смысла смешивать struct а также class почему надо думать сложнее и заботиться о том, class или же struct?

Преимущество struct над class заключается в том, что он сохраняет одну строку кода, если придерживается "сначала общедоступных членов, то частных". В этом свете я нахожу ключевое слово class бесполезный.

Вот еще одна причина использования только struct и никогда class, В некоторых рекомендациях по стилю кода для C++ предлагается использовать строчные буквы для макрокоманд функций. Обоснованием этого является то, что при преобразовании макроса во встроенную функцию имя менять не нужно. Тоже самое. У вас есть хорошая структура в стиле C, и однажды вы обнаружите, что вам нужно добавить конструктор или какой-то удобный метод. Вы меняете это на class? Везде?

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

И то и другое struct а также class те же самые под капотом, но с разными настройками видимости по умолчанию, struct по умолчанию публично и classпо умолчанию частный. Вы можете изменить одно на другое с соответствующим использованиемprivate а также public. Оба они позволяют наследование, методы, конструкторы, деструкторы и все остальные преимущества объектно-ориентированного языка.

Однако одно огромное различие между ними заключается в том, что struct как ключевое слово поддерживается в C, тогда как classне является. Это означает, что можно использоватьstruct в включаемом файле, который может быть #include в C++ или C, пока struct это простой стиль C struct и все остальное во включаемом файле совместимо с C, то есть нет особых ключевых слов C++, таких как private, public, без методов, без наследования и т. д. и т. д.

Стиль переменного тока struct может использоваться с другими интерфейсами, которые поддерживают использование стиля C. struct для передачи данных туда и обратно через интерфейс.

Стиль переменного тока struct- это своего рода шаблон (не шаблон C++, а скорее шаблон или трафарет), описывающий структуру области памяти. За прошедшие годы были созданы интерфейсы, которые можно использовать с C и с подключаемыми модулями C (здесь мы видим Java, Python и Visual Basic), некоторые из которых работают со стилем C.struct.

Они в значительной степени одно и то же. Благодаря магии C++, структура может содержать функции, использовать наследование, создаваться с использованием "new" и так далее, как класс

Единственное функциональное отличие состоит в том, что класс начинается с прав частного доступа, а структура начинается с открытого. Это поддерживать обратную совместимость с C.

На практике я всегда использовал структуры как носители данных, а классы - как объекты.

Учебный класс.

Члены класса по умолчанию закрыты.

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.

Структура - это класс, члены которого по умолчанию являются публичными.

struct test_one {
    int main_one;
};

Средства main_one является частным, т.е.

class test_one {
  public:
    int main_one;
};

Я использую структуры для структур данных, где члены могут принимать любое значение, так проще.

После многих лет программирования на C++, моем основном языке, я пришел к окончательному выводу, что это еще одна тупая функция C++.

Между ними нет реальной разницы, и нет причин, по которым я должен тратить дополнительное время на решение, должен ли я определять свою сущность как структуру или класс.

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

У меня никогда не было случая, когда частное наследование было правильным решением. Да, я пытался изобрести проблемы для использования частного наследования, но это не сработало. А Java, модель для подражания объектно-ориентированного программирования, по умолчанию использует общедоступное наследование, если вы не используете ключевые слова-средства доступа. И, кстати, Java не позволяет использовать ключевые слова-аксессоры в унаследованных классах, они могут быть только унаследованы публично. Как видите, здесь действительно упала команда cpp.

Структуры по умолчанию имеют открытый доступ, а классы по умолчанию имеют частный доступ.

Лично я использую структуры для объектов передачи данных или в качестве объектов значения. Когда используется как таковой, я объявляю все члены как const, чтобы предотвратить изменение другим кодом.

Просто чтобы решить эту проблему с точки зрения C++20 Standardese (работает с N4860) ...

Класс является типом. Ключевые слова "" и "" (и "") - в грамматике C++ - ключи класса s, и единственное функциональное значение выбора или:

Класс ключ определяет , является ли ... доступ публичным или частным порядком по умолчанию (11.9).

Доступность элемента данных по умолчанию

То, что ключевое слово приводит к членам по умолчанию private, а ключевое слово struct приводит к членам по умолчанию public, документировано в примерах в 11.9.1:

класс X {int a; // X :: a является закрытым по умолчанию: используемый класс

...против...

struct S {int a; // S :: a по умолчанию общедоступен: структура используется

Доступность базового класса по умолчанию

1.9 также говорит:

В отсутствие спецификатора доступа для базового класса publicпредполагается, когда производный класс определен с помощью ключа класса и privateпредполагается, когда класс определен с помощью ключа класса .

Обстоятельства, при которых требуется последовательное использование структуры или класса ...

Есть требование:

При повторном объявлении, частичной специализации, явной специализации или явном создании экземпляра шаблона класса ключ класса должен согласовываться по сути с объявлением исходного шаблона класса (9.2.8.3).

... в любом разработанной-типа-спецификатор , то enumключевое слово должно использоваться для ссылки на перечисление (9.7.1), ключ класса должен использоваться для ссылки на (11.5), и либо ключ класса, либо ключ класса должен использоваться для ссылки на класс, не являющийся объединением (11.1 ).

Предоставляется следующий пример (когда согласованность не требуется):

struct S {} s; класс S * p = & s; // OK

Тем не менее, некоторые компиляторы могут об этом предупреждать.


Интересно, что в то время как типы, которые вы создаете, и union все называются "классами", у нас есть ...

Структура стандартного макета - это стандартный класс макета, определенный с помощью ключа класса structили ключ класса class.

... так что на стандартном языке, когда говорят о структуре стандартного макета , используется слово "struct" для обозначения "не объединения".

Мне любопытно, есть ли подобное использование «структуры» в другой терминологии, но это слишком большая работа, чтобы проводить исчерпывающий поиск в Стандарте. Комментарии по этому поводу приветствуются.

Это одно и то же с разными значениями по умолчанию classи public по умолчанию для struct), так что в теории они полностью взаимозаменяемы.

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

Я использую структуры, когда мне нужно создать тип POD или функтор.

Когда вы решите использовать struct и когда использовать класс в 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; }
};

Технически оба одинаковы в 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;
};

Например, я возвращаю студенту struct здесь методы get...() - наслаждайтесь.

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

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

Например: чтение / запись данных из файлов и потоков сокетов и т. Д. Передача аргументов функции в структуру, где аргументы функции слишком велики и синтаксис функции выглядит слишком длинным.

Технически нет большой разницы между классом и struture, кроме доступности по умолчанию. Более того, от стиля программирования зависит, как вы его используете.

Я думал, что Structs был задуман как структура данных (например, массив данных с несколькими типами данных), а классы были предназначены для упаковки кода (например, коллекции подпрограмм и функций).

:(

Функции доступа - не единственная разница между структурами и классами. Структура лучше подходит для типов POD (Plain Old Data), так как им легче управлять для компилятора и программиста. Для начинающих, которые не используют объектно-ориентированное программирование, использование структуры хорошо.

Я никогда не использую "struct" в C++.

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

Кажется, что использование структур - это скорее синтаксическое указание на то, как будут использоваться данные, но я бы предпочел просто создать класс и попытаться сделать это явным в имени класса или в комментариях.

Например

class PublicInputData {
    //data members
 };
Другие вопросы по тегам