Когда вы должны использовать класс против структуры в C ++? - PullRequest
836 голосов
/ 10 сентября 2008

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

Ответы [ 24 ]

708 голосов
/ 10 сентября 2008

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

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

200 голосов
/ 28 июля 2009

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

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

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

class X
{
  public:

  // ...
};

struct X
{
  // ...
};

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

135 голосов
/ 28 апреля 2016

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

Оба class и struct объявляют класс.

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

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

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

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

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

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

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.

53 голосов
/ 10 сентября 2008

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

struct Compare { bool operator() { ... } };
std::sort(collection.begin(), collection.end(), Compare()); 
34 голосов
/ 28 июля 2009

Из C ++ FAQ Lite :

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

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

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

21 голосов
/ 10 сентября 2008

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

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, но я обнаружил, что издержки, связанные с необходимостью декодирования сообщения в класс, обычно не стоят этого.

16 голосов
/ 27 октября 2009

Вы можете использовать "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 ++ есть и другие предостережения, но это упрощенный пример.

15 голосов
/ 28 июля 2009

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

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

    int length() {return x+y+z;}
};
9 голосов
/ 10 сентября 2008

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

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

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

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

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

8 голосов
/ 10 сентября 2008

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

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

...