C / C ++ Struct против класса

108

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

Я никогда раньше не программировал на C; но я знаю, что у него есть структуры. В C можно ли наследовать другие структуры и установить модификатор public / private?

Если вы можете сделать это на обычном C, зачем нам C ++? Что отличает классы от структуры?


источник
возможный дубликат stackoverflow.com/questions/54585/…
gonzobrains

Ответы:

147

В C ++ структуры и классы практически одинаковы; единственное отличие состоит в том, что там, где модификаторы доступа (для переменных-членов, методов и базовых классов) в классах по умолчанию являются частными, модификаторы доступа в структурах по умолчанию являются общедоступными.

Однако в C структура представляет собой просто совокупную коллекцию (общедоступных) данных и не имеет других функций, подобных классу: никаких методов, конструкторов, базовых классов и т. Д. Хотя C ++ унаследовал ключевое слово, он расширил семантику. (Это, однако, причина того, что в структурах по умолчанию все объекты общедоступны - структура, написанная как структура C, ведет себя так же.)

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

Антал Спектор-Забуски
источник
С точки зрения ООП, ребята из .Net определили это таким образом. ✓ РАССМАТРИВАЙТЕ определение структуры вместо класса, если экземпляры типа малы и обычно недолговечны или обычно встроены в другие объекты. X ИЗБЕГАЙТЕ определения структуры, если тип не обладает всеми следующими характеристиками: 1. Он логически представляет одно значение, аналогично примитивным типам (int, double и т. Д.). 2. Его размер не превышает 16 байт. 3. Он неизменен.
Abhijeet
5
@Abhijeet Это различие между структурами и классами в C #, но это просто не имеет отношения к C ++, и тем более к C. В C # классы и структуры фактически разные; не так в C ++, и C имеет только структуры без объектно-ориентированного программирования.
Антал Спектор-Забуски
не было бы лучше сохранить ту же семантику C в структуре C ++? а когда требуется использовать «структуру в стиле C ++», просто используйте класс? У меня никогда не было преимуществ наличия «расширенной» структуры в C ++ по сравнению с C. Мне нравится по-прежнему использовать структуру в том виде, в котором она разработана в C, в противном случае я использую класс с некоторыми разрешенными исключениями.
Рафаэлло,
15

Других отличий в доступе по умолчанию (публичный / частный) нет никакой разницы.

Однако некоторые магазины, которые кодируют на C и C ++, будут использовать «класс / структура» для обозначения того, что может использоваться в C и C ++ (структура), а которое - только C ++ (класс). Другими словами, в этом стиле все структуры должны работать с C и C ++. Это отчасти причина того, что разница была в первую очередь давным-давно, когда C ++ еще был известен как «C с классами».

Обратите внимание, что объединения C работают с C ++, но не наоборот. Например

union WorksWithCppOnly{
    WorksWithCppOnly():a(0){}
    friend class FloatAccessor;
    int a;
private:
    float b;
};

И аналогично

typedef union friend{
    int a;
    float b;
} class;

работает только в C

Лэнс Дидак
источник
9
Использование ключевых слов cpp в вашем коде c, а затем утверждение, что это несовместимо с cpp, довольно глупо,
Дэни
8

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

Вот соответствующий раздел из рекомендаций:

C.2: использовать класс, если у класса есть инвариант; используйте структуру, если элементы данных могут изменяться независимо

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

Если все элементы данных могут изменяться независимо друг от друга, инвариант невозможен.

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

Исполнение

Ищите структуры со всеми данными частными и классы с открытыми членами.

Приведены примеры кода:

struct Pair {  // the members can vary independently
    string name;
    int volume;
};

// but

class Date {
public:
    // validate that {yy, mm, dd} is a valid date and initialize
    Date(int yy, Month mm, char dd);
    // ...
private:
    int y;
    Month m;
    char d;    // day
};

ClassОни хорошо подходят для членов, которые, например, являются производными друг от друга или взаимосвязаны. Они также могут помочь с проверкой работоспособности при создании экземпляра. Structs хорошо подходят для «мешков с данными», где на самом деле ничего особенного не происходит, но члены логически имеют смысл сгруппироваться вместе.

Отсюда логично, что classes существуют для поддержки инкапсуляции и других связанных концепций кодирования, для которых structони просто не очень полезны.

Дэйв
источник
Еще одно соображение - портативность. structs самые портативные. Их можно использовать в C или C ++ или взад и вперед. Их также можно распаковать в Python struct, например, с помощью модуля. Если проект приоритизирует быть совместимым с другими языками, интерфейсов и систем, предпочитают structболее class. Для строго программно-внутренних дел предпочитайте class.
Дэйв,
6

В C. невозможно определить функции-члены или получить структуры друг от друга.

Кроме того, C ++ - это не только «производные структуры» C +. Шаблоны, ссылки, определенные пользователем пространства имен и перегрузка операторов - все это не существует в C.

Йоханнес Шауб - litb
источник
Я знаю, что шаблоны и т. Д. Не существуют в C, но я не знал powerо структурах в C. Итак, C ++ использует структуры только для «обратной» совместимости с C?
4
Просто для обратной совместимости? С практической точки зрения, в этом, вероятно, что-то есть, но различие может быть сигналом намерения: когда я использую, structя имею в виду в основном пассивный тип POD.
dmckee --- котенок экс-модератора
@dmckee: Как бы то ни было, большинство функторов STL (т.е. std::less) определены как структуры, а не классы.
Билли Онил,
1
C ++ не полностью поддерживает обратную совместимость с C. Можно сказать, что ключевое слово struct является приспособлением для разработчиков C. Мне нравится ключевое слово struct для классов, которые просто хранят данные в упорядоченном виде, но сами не предоставляют (много) логики.
ypnos
@ypnos: См. мой последний комментарий. Единственное различие между ними состоит в том, что одни члены по умолчанию являются общедоступными, а другие - частными.
Билли Онил
3

Еще одно отличие C ++: когда вы наследуете класс из структуры без какого-либо спецификатора доступа, он становится публичным наследованием, тогда как, как и в случае класса, это частное наследование.

Марсоход
источник
1

C ++ использует структуры в первую очередь для 1) обратной совместимости с C и 2) типов POD. У структур C нет методов, наследования или видимости.

Крис Хафи
источник
2
Как бы то ни было, большинство функторов STL (т.е. std::less) определены как структуры, а не классы.
Билли Онил
3
Обратите внимание, что у структур C ++ есть методы, наследование и видимость.
robertwb 03
c struct может включать указатель на функцию, хотя как type (* addr) (params);
Ошибка