13

We often use c++ structs to define data structure as opposed to class which can be a complete module with member methods. Now deep down, we know they both are the same (loosely speaking).

The fact that we often use/treat structs as data only entities creates this urge that we not add default constructors as well. But constructors are always great, they make things simpler and help eliminate errors.

Would it be frown upon if add default constructors to my data structures?

Does implementing default constructor also make the struct Non-POD (plain old data type) provided other criteria are met?

To put things in perspective, consider a simple example but in reality the struct would be much larger.

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

Every time I create a method, I have to worry about (to say the least) if I forgot to set some value. Imagine I forget to set temperature and apply the method to system which is now a random high value and causes mayhem. Or I forgot to set duration and now the method applies itself for an unknown high duration.

Why should I take responsibility to initialize the object every time instead of implementing its constructor which guarantees it?

  • If you need to enforce that only certain values are allowed, then you don't quite have a plain old data type. If you just want convenient ways of initializing structs, plain old functions will do that. – Doval Nov 11 '14 at 16:54
  • It depends on what these constructors are doing. I think it is completely reasonable to have a constructor on a simple struct if it is just setting field values in basic ways. – Steven Burnap Nov 11 '14 at 16:57
  • @Doval that's not the question, I updatd the post. Steven: yes the constructors will only be just assigning default values. – zadane Nov 11 '14 at 17:26
  • @StevenBurnap: If the constructor does anything more than just setting field values in basic ways it is only more appropriate to have it. Even on a struct. – Jan Hudec Nov 11 '14 at 17:29
  • 2
    What I mean is, if you start finding complicated logic in the constructor, it is likely that you should make it into a class. (IMHO) But it's really just a style question as the only actual difference between struct and class is that one defaults to private and the other to public. – Steven Burnap Nov 11 '14 at 17:31
13

Sometimes it's appropriate to add constructor to a struct and sometimes it is not.

Adding constructor (any constructor) to a struct prevents using aggregate initializer on it. So if you add a default constructor, you'll also have to define non-default constructor initializing the values. But if you want to ensure that you always initialize all members, it is appropriate.

Adding constructor (any constructor, again) makes it non-POD, but in C++11 most of the rules that previously applied to POD only were changed to apply to standard layout objects and adding constructors don't break that. So the aggregate initializer is basically the only thing you lose. But it is also often a big loss.

8

With C++11 you can do

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

And whenever you forget to initialize something, you get default initialization.

-1

Quick Answer:

It depends on what do you want to achieve.

Long, Extended, Boring Answer:

You hit the nail.

I usually dislike that "C++" allows "Struct (s)" allows to declare methods. Preferably, I use explicit "Class (es)" for methods required and P.O.D. "Struct (s)" for only fields.

Yet, I agree that some basic simple operations, like:

  • assign initial values ("constructor")
  • make a copy of a structure ("copy constructor)
  • assign values to an existing structure ("overload assign operator")

Are required, and, in those circumstances, methods for structures, make sense.

Suggestion

Another potential solution is to use P.O.D. structures, but, still conceptually treat them as classes and objects.

Wrap those declarations in a namespace, and, add global functions, for the most important actions.

The code declaration could be similar to this:

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

The code that applies the solution, could be something like this:

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

This alternative approach is better when a huge memory allocation of data is required, or interacting with other low-level shared libraries.

This approach, with some changes, is applied in Game Development.

Extra

Personally, I consider a syntax extension for "C++", or even, a new "C++" based P.L. that solves this issue:

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

Cheers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.