Yapılara kurucu eklemeli miyiz?


14

Üye yapısıyla tam bir modül olabilen sınıfın aksine veri yapısını tanımlamak için genellikle c ++ yapıları kullanırız. Şimdi derinlerde, ikisinin de aynı olduğunu biliyoruz (gevşek konuşma).

Yapıları sık sık yalnızca veri varlıkları olarak kullandığımız / ele aldığımız, varsayılan kurucular da eklemediğimiz bu dürtü yaratır. Ancak yapıcılar her zaman harikadır, işleri basitleştirir ve hataları ortadan kaldırmaya yardımcı olurlar.

Veri yapılarıma varsayılan kurucuları eklersem kaşlarını çatır mıydı?

Varsayılan yapıcıyı uygulamak , diğer ölçütlerin karşılanması koşuluyla POD Olmayan Yapıyı (düz eski veri türü) da yapar mı?

İşleri perspektife sokmak için basit bir örnek düşünün, ancak gerçekte yapı çok daha büyük olurdu.

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

Her yöntem oluşturduğumda, bir değer ayarlamayı unuttuğumda (en azından söylemek gerekirse) endişelenmem gerekiyor. temperatureŞimdi rasgele yüksek bir değer olan ve kargaşaya neden olan yöntemi sisteme ayarlamayı ve uygulamayı unuttuğumu düşünün . Ya da ayarlamayı unuttum durationve şimdi yöntem bilinmeyen yüksek bir süre için kendini uyguluyor.

Nesneyi, onu garanti eden yapıcısını uygulamak yerine her seferinde başlatma sorumluluğunu üstlenmeliyim?


Yalnızca belirli değerlere izin verildiğini uygulamanız gerekiyorsa, eski bir veri türünüz yoktur. Sadece yapıları başlatmanın uygun yollarını istiyorsanız, düz eski işlevler bunu yapacaktır.
Doval

Bu yapıcıların ne yaptığına bağlıdır. Alan değerlerini sadece temel yollarla ayarlıyorsa, basit bir yapı üzerinde bir kurucuya sahip olmanın tamamen mantıklı olduğunu düşünüyorum.
Robot Gort

@Doval soru değil, ben yazı güncelleyin. Steven: Evet, yapıcılar sadece varsayılan değerleri atayacaklar.
zadane

@StevenBurnap: Yapıcı yalnızca alan değerlerini temel yollarla ayarlamaktan başka bir şey yaparsa , buna sahip olmak sadece daha uygundur. Bir yapıda bile.
Jan Hudec

2
Demek istediğim, yapıcıda karmaşık mantık bulmaya başlarsanız, muhtemelen bir sınıfa dönüştürmeniz gerekir. (IMHO) Ama bu gerçekten sadece bir stil sorusu structve classbiri varsayılanı diğeri halka açıktır.
Robot Gort

Yanıtlar:


13

Bazen bir yapıya yapıcı eklemek bazen uygun değildir.

Bir yapıya kurucu (herhangi bir kurucu) eklemek, üzerinde toplu başlatıcı kullanılmasını önler. Dolayısıyla, varsayılan bir kurucu eklerseniz, değerleri başlatan varsayılan olmayan kurucuyu da tanımlamanız gerekir. Ancak her zaman tüm üyeleri başlattığınızdan emin olmak istiyorsanız, bu uygun olur.

Yapıcı (yine herhangi bir kurucu) eklenmesi onu POD yapmaz, ancak C ++ 11'de daha önce POD'a uygulanan kuralların çoğu yalnızca standart mizanpaj nesnelerine uygulanacak şekilde değiştirildi ve yapıcıları eklemek bunu kırmaz. Bu nedenle, toplam başlatıcı, temelde kaybettiğiniz tek şeydir. Ancak bu genellikle büyük bir kayıptır.


8

İle 11 C ++ Yapabileceğiniz

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

Ve bir şeyi başlatmayı unuttuğunuzda, varsayılan başlatmayı alırsınız.


-1

Hızlı cevap:

Neyi başarmak istediğinize bağlıdır.

Uzun, Genişletilmiş, Sıkıcı Cevap:

Çiviye vurdun.

Genellikle "C ++" izin verir "Struct (s)" yöntemleri bildirmek için izin verir. Tercihen, gerekli yöntemler için açık "Class (s)" ve yalnızca alanlar için POD "Struct (s)" kullanıyorum.

Yine de, bazı temel basit işlemlerin, örneğin:

  • başlangıç ​​değerlerini ata ("yapıcı")
  • bir yapının kopyasını yap ("kopya oluşturucu)
  • mevcut bir yapıya değerler atama ("aşırı yük atama operatörü")

Gereklidir ve bu durumlarda yapılar için yöntemler mantıklıdır.

Öneri

Başka bir potansiyel çözüm, POD yapılarını kullanmaktır, ancak yine de kavramsal olarak bunları sınıflar ve nesneler olarak ele alır.

Bu bildirimleri bir ad alanına sarın ve en önemli eylemler için genel işlevler ekleyin.

Kod bildirimi buna benzer olabilir:

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

Çözümü uygulayan kod şöyle olabilir:

#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(...)

Bu alternatif yaklaşım, büyük miktarda bellek tahsisi gerektiğinde veya diğer düşük seviyeli paylaşılan kütüphanelerle etkileşime girdiğinde daha iyidir.

Bu yaklaşım bazı değişikliklerle Oyun Geliştirme'de uygulanmaktadır.

Ekstra

Şahsen, ben "C ++" sözdizimi uzantısı, hatta bu sorunu çözen yeni bir "C ++" tabanlı PL düşünün:

// "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

Şerefe.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.