Каковы различия между структурой и классом в C++?

Этот вопрос уже задавался в контексте C#/.NET.

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

Начну с очевидной разницы:

  • Если вы не укажете public: или же private:члены структуры являются общедоступными по умолчанию; члены класса являются частными по умолчанию.

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

31 ответ

Решение

Вы забываете хитрое 2-е различие между классами и структурами.

Quoth стандарт (§11.2.2 в C++98 через C++11):

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

И просто для полноты, более широко известное различие между классом и структурой определено в (11.2):

Члены класса, определенного с помощью ключевого слова class, по умолчанию являются закрытыми. Члены класса, определенного с помощью ключевых слов struct или union, являются открытыми по умолчанию.

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

Цитируя C++ FAQ,

[7.8] В чем разница между структурой ключевых слов и классом?

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

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

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

Стоит помнить о происхождении C++ и его совместимости с C.

C имеет структуры, не имеет понятия инкапсуляции, поэтому все является открытым.

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

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

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

Если бы C++ появился с нуля, без истории, то у него, вероятно, было бы только одно такое ключевое слово. Это также вероятно не сделало бы воздействие, которое это оказало.

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

Члены класса по умолчанию закрыты. Члены Struct являются публичными по умолчанию. Кроме того, нет никаких других отличий. Также посмотрите этот вопрос.

По словам Страуструпа на языке программирования C++:

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

Функционально, нет никакой разницы, кроме государственного / частного

1) Члены класса по умолчанию являются закрытыми, а члены структуры являются открытыми по умолчанию.

Например, программа 1 не работает при компиляции, а программа 2 работает нормально.

// Program 1
#include <stdio.h>

class Test {
    int x; // x is private
};
int main()
{
  Test t;
  t.x = 20; // compiler error because x is private
  getchar();
  return 0;
}
Run on IDE
// Program 2
#include <stdio.h>

struct Test {
    int x; // x is public
};
int main()
{
  Test t;
  t.x = 20; // works fine because x is public
  getchar();
  return 0;
}

2) При извлечении структуры из класса / структуры спецификатор доступа по умолчанию для базового класса / структуры является общедоступным. А при получении класса спецификатор доступа по умолчанию является закрытым.

Например, программа 3 завершается неудачно при компиляции, а программа 4 работает нормально.

// Program 3
#include <stdio.h>

class Base {
public:
    int x;
};

class Derived : Base { }; // is equilalent to class Derived : private Base {}

int main()
{
  Derived d;
  d.x = 20; // compiler error becuase inheritance is private
  getchar();
  return 0;
}
Run on IDE
// Program 4
#include <stdio.h>

class Base {
public:
    int x;
};

struct Derived : Base { }; // is equilalent to struct Derived : public Base {}

int main()
{
  Derived d;
  d.x = 20; // works fine becuase inheritance is public
  getchar();
  return 0;
}

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

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

По сути, структуры - это данные, классы - это код.

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

Помимо того факта, что каждый является отдельным типом абстракции, классы предоставляют решения головоломки с именами кода на языке Си. Поскольку вы не можете иметь более одной функции с одним и тем же именем, разработчики использовали шаблон _(). например, mathlibextreme_max(). Группируя API-интерфейсы в классы, аналогичные функции (здесь мы называем их "методами") можно группировать вместе и защищать от именования методов в других классах. Это позволяет программисту лучше организовать свой код и увеличить повторное использование кода. В теории, по крайней мере.

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

Разница между class а также structэто разница между ключевыми словами, а не между типами данных. Эти два

struct foo : foo_base { int x;};
class bar : bar_base { int x; };

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

  • foo::x публично и foo_base передается по наследству публично
  • bar::x является частным и bar_base передается по наследству
  1. Член класса, определенного с помощью ключевого слова class являются private по умолчанию. Члены класса, определенного с помощью ключевых слов struct (или же union) являются public по умолчанию.

  2. В отсутствие спецификатора доступа для базового класса, public предполагается, когда производный класс объявлен struct а также private предполагается, когда класс объявлен class,

  3. Вы можете объявить enum class но не enum struct,

  4. Ты можешь использовать template<class T> но нет template<struct T>,

Также обратите внимание, что стандарт C++ позволяет вам объявить тип как struct, а затем использовать class при объявлении типа и наоборот. Также, std::is_class<Y>::value является true для Y быть struct и class, но это false для enum class,

  1. Члены структуры являются открытыми по умолчанию, члены класса являются закрытыми по умолчанию.
  2. По умолчанию наследование для структуры от другой структуры или класса является публичным. По умолчанию наследование для класса от другой структуры или класса является частным.
class A{    
public:    
    int i;      
};

class A2:A{    
};

struct A3:A{    
};


struct abc{    
    int i;
};

struct abc2:abc{    
};

class abc3:abc{
};


int _tmain(int argc, _TCHAR* argv[])
{    
    abc2 objabc;
    objabc.i = 10;

    A3 ob;
    ob.i = 10;

    //A2 obja; //privately inherited
    //obja.i = 10;

    //abc3 obss;
    //obss.i = 10;
}

Это на VS2005.

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

template<class T> // OK
template<struct T> // ERROR, struct not allowed here

Нет в спецификации, нет. Основное различие заключается в ожиданиях программистов, когда они читают ваш код через 2 года. структуры часто предполагаются как POD. Структуры также используются в метапрограммировании шаблонов, когда вы определяете тип для целей, отличных от определения объектов.

Еще одна вещь, на которую следует обратить внимание: если вы обновили устаревшее приложение, в котором были использованы классы, вы можете столкнуться со следующей проблемой:

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

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

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

Вот хорошее объяснение: http://carcino.gen.nz/tech/cpp/struct_vs_class.php

Итак, еще раз: в C++ структура идентична классу, за исключением того, что члены структуры имеют общедоступную видимость по умолчанию, но члены класса имеют частную видимость по умолчанию.

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

ISO IEC 14882-2003

9 классов

§3

Структура - это класс, определенный с помощью ключа класса struct; его члены и базовые классы (раздел 10) являются общедоступными по умолчанию (раздел 11).

  • , В классах все члены по умолчанию являются частными, но в структуре члены являются открытыми по умолчанию.

    1. Не существует таких терминов, как конструктор и деструктор для структур, но для класса компилятор создает значение по умолчанию, если вы не предоставите.

    2. Размер пустой структуры равен 0 байтам, поскольку размер пустого класса равен 1 байт. Тип доступа по умолчанию для структуры public. Структура обычно должна использоваться для группировки данных.

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

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

    В C++ структуры и классы передаются по значению, если явно не обращены ссылки. В других языках классы и структуры могут иметь различную семантику - т.е. объекты (экземпляры классов) могут передаваться по ссылке, а структуры могут передаваться по значению. Примечание. Есть комментарии, связанные с этим вопросом. Смотрите страницу обсуждения, чтобы добавить к разговору.

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

Что может быть интересно отметить (особенно потому, что спрашивающий, вероятно, использует MSVC++, поскольку он упоминает "неуправляемый" C++), - это то, что Visual C++ жалуется при определенных обстоятельствах, если класс объявлен с class а затем определяется с struct (или, возможно, наоборот), хотя стандарт гласит, что это совершенно законно.

Хотя это подразумевается другими ответами, прямо не упоминается - что структуры совместимы с C, в зависимости от использования; классы нет.

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

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

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

В любом случае, что мне нужно обосновать, так это то, что Класс - это гораздо более широкое понятие, применимое к реальному миру, тогда как Структура - это примитивная Концепция с плохой внутренней организацией (хотя структура Eventhough следует концепциям ООП, они имеют плохое значение)

Вы могли бы рассмотреть это для рекомендаций о том, когда идти для структуры или класса, https://msdn.microsoft.com/en-us/library/ms229017%28v=vs.110%29.aspx.

√ УЧИТЫВАЙТЕ определение структуры вместо класса, если экземпляры типа маленькие и обычно недолговечные или обычно встроены в другие объекты.

X ИЗБЕГАЙТЕ определения структуры, если тип не имеет всех следующих характеристик:

Логически представляет одно значение, похожее на примитивные типы (int, double и т. Д.).

Размер экземпляра менее 16 байт.

Это неизменно.

Это не должно быть упаковано часто.

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

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

Если вы прочитаете некоторые принципы разработки программного обеспечения, вы обнаружите, что большинство стандартов не могут быть легко реализованы без занятий. например: http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29

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

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

фе

      class Time
{
    int minutes;
    int seconds;
}

struct Sizes
{
    int length;
    int width;
};

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

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

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

И да, самое незабытое различие, которое я забыл упомянуть, состоит в том, что класс поддерживает скрытие данных, а также поддерживает операции, выполняемые со встроенными типами данных, а struct - нет!

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

struct Foo {
    int a;
};

class Bar {
    int a;
};

class Tester {
    Foo m_Foo = Foo();
    Bar m_Bar = Bar();

public:
    Tester() {}
};

int main() {
    auto myTester = Tester();
}

Запустите этот код и проверьте myTester. Вы обнаружите, что для m_Foo структура m_Foo.a была инициализирована равной 0, но для m_Bar класс m_Bar.a неинициализирован. Таким образом, кажется, есть разница в том, что конструктор по умолчанию делает для структуры против класса. Я вижу это с Visual Studio.

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

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

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

Например:

Class MyClass
{
    Public Int DataMember;  //By default, accessibility of class data members 
                            //will be private. So I am making it as Public which 
                            //can be accessed outside of the class.
}

В основном методе
Я могу создать экземпляр этого класса, используя оператор new, который выделяет память для этого класса
и сохраняет базовый адрес этого в переменной типа MyClass (_myClassObject2).

Static Public void Main (string[] arg)
{
    MyClass _myClassObject1 = new MyClass();
    _myClassObject1.DataMember = 10;

    MyClass _myClassObject2 = _myClassObject1;
    _myClassObject2.DataMember=20;
}

В приведенной выше программе MyClass _myClassObject2 = _myClassObject1; инструкция указывает, что обе переменные типа MyClass

  1. myClassObject1
  2. myClassObject2

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

Поэтому, если какие-либо изменения, которые мы вносим в один из объектов типа MyClass, будут влиять на другие
так как оба указывают на одну и ту же область памяти.

"_myClassObject1.DataMember = 10;" в этой строке оба элемента данных объекта будут содержать значение 10.
"_myClassObject2.DataMember = 20;" в этой строке оба элемента данных объекта будут содержать значение 20.
В конце концов, мы получаем доступ к элементам данных объекта через указатели.

В отличие от классов, структуры являются типами значений. Например:

Structure MyStructure
{
    Public Int DataMember;  //By default, accessibility of Structure data 
                            //members will be private. So I am making it as 
                            //Public which can be accessed out side of the structure.
}

Static Public void Main (string[] arg)
{
    MyStructure _myStructObject1 = new MyStructure();
    _myStructObject1.DataMember = 10;

    MyStructure _myStructObject2 = _myStructObject1;
    _myStructObject2.DataMember = 20;
}

В вышеуказанной программе
создание экземпляра объекта типа MyStructure с использованием оператора new и
сохранение адреса в переменной _myStructObject типа MyStructure и
присваивание значения 10 элементу данных структуры с использованием "_myStructObject1.DataMember = 10".

В следующей строке
Я объявляю другую переменную _myStructObject2 типа MyStructure и присваиваю _myStructObject1 в нее.
Здесь компилятор.NET C# создает еще одну копию объекта _myStructureObject1 и
назначает эту область памяти в переменную MyStructure _myStructObject2.

Поэтому любое изменение, которое мы вносим в _myStructObject1, никогда не повлияет на другую переменную _myStructObject2 типа MyStructrue.
Вот почему мы говорим, что структуры являются типами значений.

Поэтому непосредственным базовым классом для класса является Object, а непосредственным базовым классом для Structure является ValueType, который наследуется от Object.
Классы будут поддерживать наследование, а структуры - нет.

Как мы говорим это?
И в чем причина этого?
Ответ - Классы.

Он может быть абстрактным, запечатанным, статичным и частичным, и не может быть частным, защищенным и защищенным внутри.

Другие вопросы по тегам