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

669

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

  • 40
    Это относится не только к C ++, но и к любому языку, который предоставляет как структуры, так и классы.
  • 2
    Я все еще не согласен - я подхожу к этому вопросу семантически. Возможно, есть некоторые технические различия, но семантически они не являются. Структуры действительно полезны для создания типов значений, а классы - нет.
Показать ещё 16 комментариев
Теги:
class
struct
oop
ooad

23 ответа

532
Лучший ответ

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

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

  • 81
    Структура без модификаторов или методов называется структурой POD, которая существует как обратно совместимый интерфейс с библиотеками C, поскольку (предположительно) она гарантированно будет размещена так, как если бы она была структурой C. Помимо этого единственного исключения, единственное отличие, как указано.
  • 25
    @ workmad3: имя вводит в заблуждение, но 9/4 (C ++ 03) гласит: «POD-структура - это агрегатный класс, который не имеет нестатических членов-данных типа non-POD-struct, non-POD-union (или массив таких типов) или ссылка, и не имеет никакого пользовательского оператора назначения копирования и никакого пользовательского деструктора. " Нет никаких ограничений на использование "class" ключ-класс и нет никаких ограничений на использование "public" (см. 8.5.1 / 1 для совокупных требований). Это не разница между "структура" и "класс".
Показать ещё 11 комментариев
149

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

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

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

class X
{
  public:

  // ...
};

struct X
{
  // ...
};

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

  • 0
    Хороший пример относительно наследственных различий: здесь .
  • 5
    Используете ли вы struct или class , не имеет никакого отношения к тому, является ли ваш объект POD или вам нужно определить конструктор / деструктор копирования. Функции-члены также не имеют отношения к POD. Когда я перечитываю то, что вы написали, я вижу, что вы не предлагаете иначе, но нынешняя формулировка сбивает с толку
Показать ещё 2 комментария
57

В существующих ответах есть много неправильных представлений.

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

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

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

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

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

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

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

struct Foo
{
   int x;
};

class Bar
{
public:
   int x;
};

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

class Foo;
struct Bar;

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

а следующие выражения оцениваются как true:

std::is_class<Foo>::value
std::is_class<Bar>::value
  • 11
    Это было очень информативно, и, честно говоря, мой любимый ответ. Все остальные относятся к ним как к отдельным сущностям, когда под капотом они одинаковы. Интересно, считается ли определение структуры в среде Arduino классом cpp, поскольку он скомпилирован с использованием g ++.
  • 2
    @Ben Конечно, это так. Компилятор Arduino компилирует C ++; это конец.
Показать ещё 4 комментария
49

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

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

Из С++ FAQ Lite:

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

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

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

  • 1
    Я не понимаю, почему они утверждают, что структура и класс функционально одинаковы, но говорят, что предпочитают один над другим в определенных случаях без каких-либо аргументов.
  • 2
    Причина в соглашении. Компилятору все равно, какой вы используете, но другому разработчику, изучающему ваш код, будет легче понять, что вы имели в виду.
Показать ещё 1 комментарий
16

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

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

  • 0
    То же самое может быть достигнуто в C.
  • 10
    Или вы могли бы просто реализовать operator >> в классе вместо написания функции processMessage , что бы ваш C ++ выглядел больше как правильный C ++, а не как C.
Показать ещё 6 комментариев
13

Вы можете использовать "struct" в С++, если вы пишете библиотеку, внутри которой С++, но API можно вызвать либо с помощью кода C, либо с С++. Вы просто создаете один заголовок, который содержит структуры и глобальные функции API, которые вы открываете для кода C и С++ следующим образом:

// C access Header to a C++ library
#ifdef __cpp
extern "C" {
#endif

// Put your C struct 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 и С++ существуют другие оговорки, но это упрощенный пример.

  • 2
    Лучший подходящий ответ. C-совместимость - действительно самая важная причина. все остальные вещи, такие как доступ по умолчанию, являются эзотерическими.
7

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

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

    int length() {return x+y+z;}
};
  • 1
    +1 за пример структуры с некоторыми функциями-членами, которые не чувствуют, что вы "убрали структуру".
7

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

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

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

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

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

  • 1
    Это не правильное использование POD. Структура (или класс) может быть структурой POD, если (и только если) она содержит ТОЛЬКО членов POD.
  • 4
    «Предсказуемая семантика копирования»: Симантика такая же, как и для класса (и имеют те же проблемы (мелкое копирование)).
Показать ещё 1 комментарий
5

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

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

3

Чтобы ответить на мой собственный вопрос (бесстыдно), Как уже упоминалось, привилегии доступа являются единственной разницей между ними в С++.

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

2

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

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

2

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

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

2

Это почти то же самое. Благодаря магии С++ структура может содержать функции, использовать наследование, созданные с использованием "новых" и т.д., Как класс

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

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

1

Класс.

По умолчанию члены класса являются закрытыми.

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

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

1

Когда вы решите использовать struct и когда использовать класс в С++?

Я использую 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; }
};
  • 1
    Этот ответ показывает признаки возраста :) std::binary_function<> не просто устарела, c ++ 17 даже удаляет его.
  • 0
    Не удивительно, поскольку он был написан во времена C ++ 03, языка, определенного 15 лет назад.
0

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

  • 0
    Зачем вам нужно изменить его на class ? Вы думаете, что класс, определенный с ключевым словом struct не может иметь функции-члены или конструктор?
  • 0
    @LightnessRacesinOrbit из-за 1. согласованности и 2. некоторые статические анализаторы жалуются на нарушение 1.
Показать ещё 2 комментария
0

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

0

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

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

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

0

Технически оба одинаковы в С++ - например, возможно, что у структуры есть перегруженные операторы и т.д.

Однако:

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

Надеюсь, что это поможет.

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

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

-1

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

: (

-5

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

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

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

например.

class PublicInputData {
    //data members
 };
  • 0
    По моему мнению, «синтаксическое указание на то, как будут использоваться данные», является вполне веской причиной для использования структуры, особенно если альтернативой является использование комментария или имени в имени класса.
  • 1
    Разве объявление struct уже не будет достаточно явным, что члены класса будут по умолчанию открытыми?
Показать ещё 1 комментарий
-8

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню