Должны ли мы добавить конструкторы к структурам?

14

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

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

Будет ли одобрено добавить конструкторы по умолчанию в мои структуры данных?

Делает ли реализация конструктора по умолчанию также структуру struct Non-POD (обычный старый тип данных) при условии соблюдения других критериев?

Чтобы представить вещи в перспективе, рассмотрим простой пример, но на самом деле структура была бы намного больше.

struct method
{
    char    name[32];
    float   temperature;
    int     duration;
};

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

Почему я должен брать на себя ответственность каждый раз инициализировать объект, а не реализовывать его конструктор, который это гарантирует?

zadane
источник
Если вам нужно обеспечить, чтобы разрешались только определенные значения, то у вас не совсем старый тип данных. Если вам просто нужны удобные способы инициализации структур, это сделают простые старые функции.
Довал
Это зависит от того, что делают эти конструкторы. Я думаю, что вполне разумно иметь конструктор в простой структуре, если он просто устанавливает значения полей основными способами.
Gort the Robot
@Doval, это не вопрос, я обновил пост. Стивен: да, конструкторы будут только назначать значения по умолчанию.
Заданье
@StevenBurnap: Если конструктор делает что-то большее, чем просто установка значений полей базовыми способами, это только более уместно иметь. Даже на структуре.
Ян Худек
2
Я имею в виду, что если вы начинаете находить сложную логику в конструкторе, вполне вероятно, что вы должны превратить ее в класс. (ИМХО) Но это действительно только вопрос стиля , как только действительное различие между structиclass является то , что один по умолчанию частных и другая общественности.
Gort the Robot

Ответы:

13

Иногда целесообразно добавить конструктор в структуру, а иногда нет.

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

Добавление конструктора (опять же, любого конструктора) делает его не POD, но в C ++ 11 большинство правил, которые ранее применялись только к POD, были изменены для применения к стандартным объектам компоновки, и добавление конструкторов не нарушает этого. Таким образом, агрегатный инициализатор - это единственное, что вы теряете. Но это также часто большая потеря.

Ян Худек
источник
8

С C ++ 11 вы можете сделать

struct method
{
    char    name[32] {};
    float   temperature = 42.141521;
    int     duration = -6;
};

И когда вы забудете что-то инициализировать, вы получите инициализацию по умолчанию.

Vorac
источник
-1

Быстрый ответ:

Это зависит от того, чего вы хотите достичь.

Длинный, расширенный, скучный ответ:

Вы попали в гвоздь.

Мне обычно не нравится, что "C ++" позволяет "Struct (s)" позволяет объявлять методы. Предпочтительно, я использую явные «Класс (ы)» для обязательных методов и POD «Структуру (ы)» только для полей.

Тем не менее, я согласен, что некоторые основные простые операции, такие как:

  • назначить начальные значения («конструктор»)
  • сделать копию структуры ("конструктор копирования")
  • присваивать значения существующей структуре («оператор присваивания перегрузки»)

Требуются, и, в этих обстоятельствах, методы для структур, имеют смысл.

Предложение

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

Оберните эти объявления в пространство имен и добавьте глобальные функции для наиболее важных действий.

Объявление кода может быть похожим на это:

namespace Customers
{
  struct CustomerStruct
  {
    char[255] FirstName;
    char[255] LastName;
    int Age;
    bool IsAlive;
    bool IsMarried;
  }; // struct

  CustomerStruct* CreateCustomer
  (
    char* NewFirstName;
    char* NewLastName;
    int NewAge;
    bool NewIsAlive;
    bool NewIsMarried;
  )
  {
    CustomerStruct* NewCustomer = new CustomerStruct();
      NewCustomer->FirstName = NewFirstName;
      NewCustomer->LastName = NewLastName;
      NewCustomer->Age = NewAge;
      NewCustomer->IsAlive = NewIsAlive;
      NewCustomer->IsMarried = NewIsMarried;
    return NewCustomer;
  } // CustomerStruct* CreateCustomer (...)

} // namespace

Код, который применяет решение, может быть примерно таким:

#include <Customers>

using Customers;

int main (...)
{
   int ErrorCode = 0;

   CustomerClass* ThisCustomer =
     Customers::CreateCustomer
      ("John", "Doe", 23, true, true);

   // do something with "ThisCustomer"

   delete ThisCustomer;

   return ErrorCode;
} // int main(...)

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

Этот подход с некоторыми изменениями применяется в разработке игр.

дополнительный

Лично я рассматриваю расширение синтаксиса для «C ++» или даже новый PL на основе «C ++», который решает эту проблему:

// "Plain Old Data" Structure
// No Methods, No "Functors", allowed
strict struct CustomerStruct
{
  char[255] FirstName;
  char[255] LastName;
  int Age;
  bool IsAlive;
  bool IsMarried;
}; // strict struct

// Object Oriented "Plain Old Data" Structure
// Yes, Methods and "Functors" allowed
relaxed struct CustomerStruct
{
  char[255] FirstName;
  char[255] LastName;
  int Age;
  bool IsAlive;
  bool IsMarried;

  public void Foo();
  public void Bar();

  public (void*) (SomeFunctor) ();
}; // relaxed struct

// Class and Object Oriented
class CustomerClass
{
  public char[255] FirstName;
  public char[255] LastName;
  public int Age;
  public bool IsAlive;
  public bool IsMarried;

  public void Foo();
  public void Bar();
}; // class

Приветствия.

umlcat
источник