我们应该在结构中添加构造函数吗?


14

我们经常使用c ++结构来定义数据结构,而不是使用类,类可以是带有成员方法的完整模块。从现在开始,我们知道它们都是相同的(松散地说)。

我们经常使用/处理结构作为仅数据实体的事实产生了这样的冲动,即我们也不要添加默认构造函数。但是构造函数总是很棒的,它们使事情变得更简单并有助于消除错误。

如果将默认构造函数添加到我的数据结构,会不会感到烦恼?

如果满足其他条件,实现默认构造函数还会使结构Non-POD(普通旧数据类型)吗?

为了正确理解,考虑一个简单的示例,但实际上结构会大得多。

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

每次我创建一个方法时,我都会担心(至少可以说)是否忘记设置一些值。想象一下,我忘记设置temperature该方法并将其应用于系统,该系统现在是一个随机的高值,并且会导致混乱。或者我忘了设置duration,现在该方法将其自身应用到未知的高持续时间。

为什么我应该负责每次都初始化对象,而不是执行保证它的构造函数?


如果您需要强制只允许某些值,那么您就没有普通的旧数据类型。如果您只是想要方便的初始化结构的方法,那么普通的旧函数就可以做到。
2014年

这取决于这些构造函数在做什么。我认为,如果仅以基本方式设置字段值,那么在简单结构上构造一个构造器是完全合理的。
机器人

@Doval没问题,我更新了帖子。史蒂文:是的,构造函数只会分配默认值。
zadane 2014年

@StevenBurnap:如果构造方法除了以基本方式设置字段值以外,还需要做更多的事情。即使在结构上。
2014年

2
我的意思是,如果您开始在构造函数中发现复杂的逻辑,则很可能应该将其放入一个类中。(恕我直言),但它实际上只是一个风格问题,因为之间的唯一实际的差异struct,并class是一个默认为私营和其他公众。
装填机器人

Answers:


13

有时将构造函数添加到结构中是合适的,有时不是。

将构造函数(任何构造函数)添加到结构可防止在其上使用聚合初始化程序。因此,如果添加默认构造函数,则还必须定义用于初始化值的非默认构造函数。但是,如果要确保始终初始化所有成员,则是合适的。

添加构造函数(再次是任何构造函数)使其成为非POD,但是在C ++ 11中,以前应用于POD的大多数规则仅被更改为应用于标准布局对象,并且添加构造函数不会破坏该规则。因此,聚合初始值设定项基本上是您唯一丢失的东西。但这通常也是很大的损失。


8

使用C ++ 11,您可以执行

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

而且,每当您忘记初始化某些内容时,就会得到默认的初始化。


-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 ++”的语法扩展,甚至考虑了解决此问题的基于“ C ++”的新PL:

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

干杯。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.