Jump to content

  • Log In with Google      Sign In   
  • Create Account

Struct versus class?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
46 replies to this topic

#1 cozzie   Members   -  Reputation: 1611

Like
4Likes
Like

Posted 20 January 2014 - 04:30 PM

Hi,

 

Just wondering. What do you see as the 'boundary' when you prefer a class versus a struct?

Was thinking about this when I was adding functions to my VECTOR3 struct, the number of operators has grown, and I'm thinking of also adding (inline) functions for cross- and dot- product. Included are already getting the magnitude and normalizing.

 

For now I don't see reasons to move from a struct to a class.

Operators work nice and do exactly what I want without to much code (not even sure how to do that within a class.....)

 

Somehow my mind says, as long as it's a relatively 'simple' object, just use a struct and don't 'waste classes' on it (not sure though how to explain this rationally :))

 

What are your thoughts?



Sponsor:

#2 frob   Moderators   -  Reputation: 21237

Like
26Likes
Like

Posted 20 January 2014 - 04:35 PM

Since in C++ a struct and class are very nearly identical...

 

When I see a cluster of data with no functions, or perhaps only with a constructor or very minimal functions, where the data is accessed directly, I see this as a struct. Everything is public.

 

When I see an object that has private internal state, that is manipulated and acted upon rather than used as a container for data, I see a class. Data is private, interfaces are public or protected, you shouldn't touch the innards.


Check out my personal indie blog at bryanwagstaff.com.

#3 cozzie   Members   -  Reputation: 1611

Like
0Likes
Like

Posted 20 January 2014 - 05:16 PM

Thanks, that's a nice addition. In my vector struct indeed the members are all accessible (and should be).

Would you add for example a function in the struct to calculate the cross or dot product? Or would you add 'Global functions' (yikes!! smile.png) in the same header/ cpp files


Edited by cozzie, 20 January 2014 - 05:17 PM.


#4 Brother Bob   Moderators   -  Reputation: 8194

Like
17Likes
Like

Posted 20 January 2014 - 05:28 PM

Free functions, absolutely. A member function should be seen as something that operates on the object is is called on. For example std::string::c_str, where you ask the std::string object for a pointer to its string value, or std::vector::push_back where you ask the std::vector object to append a value you supply as a parameter. But you don't ask one vector for their cross or dot product; they are simply calculations on free inputs.



#5 Strewya   Members   -  Reputation: 1433

Like
4Likes
Like

Posted 21 January 2014 - 01:40 AM

As frob mentioned, in C++ a class and a struct are pretty much identical. The choice of which to use is yours to make, seeing as the following two are very much the same:

struct Vec
{
   float x, y, z;
};

class Vec
{
public:
   float x, y, z;
};

One issue i ran into when i used a mix of structs and classes was when forward declaring them. Sometimes i would simply forget if Vec was a class or a struct. Similar with Color, Rect, Transform, etc. So i settled on using classes only, and if something needs to have all of it's members public, i simply set them as public and not protected/private.


devstropo.blogspot.com - Random stuff about my gamedev hobby


#6 Ravyne   GDNet+   -  Reputation: 7369

Like
10Likes
Like

Posted 21 January 2014 - 02:07 AM

I'm going to suggest that maybe you should do some more reading on class vs. struct, and on interface design. It sounds to me like you've got an unseasoned understanding of some things. That's not a dig at you, its just something I'm picking up on, and its very common for people to have misunderstandings that lead to here.

Just for example, you say "global functions" like its a bad thing, when in fact such "free functions" should very often be prefered. This is a common misunderstanding that stems from "object-orientitis" where one believes that all interfaces belong literally inside the class, but in reality the portion of an interface that has access to a class's internal state should be as small as possible to maximize encapsulation and maximize cohesion.

#7 Hodgman   Moderators   -  Reputation: 30380

Like
11Likes
Like

Posted 21 January 2014 - 02:43 AM

All good advice above. Global functions (aka free functions) are indeed a good thing.
It really shits me (and other OOD aficionados) that Java decided to outlaw them and also push their own modified ideas about OO... But that's another rant ;)

Anyway, in classes with private state, usually there's some kinds of constraints (aka invariants) that have to be enforced by the public functions -- e.g. Resize may check for "size < 0" before changing the private member variables. If there is a bug in the private data, e.g. Size is -1 somehow, then you only have to look at these member functions to find the cause.
If a function *can* be implemented as a free function (i.e. doesn't *have* to be a member function), it's a good choice to do so. In these cases, your free function only accesses the public members of the class -- so, if there's a bug in the private details, you know your free function can't be to blame.
That's one example of why 'decoupling' is good, but it's become a general rule of thumb in software engineering to try and keep things as loosely coupled as possible.

In your struct case, the above example doesn't apply of course, because everything is public!
However, it can still be nice organizationally to keep the data structures themselves separate from the algorithms that operate on those structures.
For example, there's an endless number of operations that could be done on a vector, so it would be nice to be able to add new operations without having to edit the shared vector struct endlessly, or make vector.h over 9000 lines long.
C# has hacked around this issue by adding "extension classes" to their language...

There's many examples of this in std::, just look at the stuff in <algorithm>, such as how searching and sorting are decoupled from std::list and std::vector!

#8 NightCreature83   Crossbones+   -  Reputation: 2824

Like
7Likes
Like

Posted 21 January 2014 - 02:48 AM

As frob mentioned, in C++ a class and a struct are pretty much identical. The choice of which to use is yours to make, seeing as the following two are very much the same:

struct Vec
{
   float x, y, z;
};

class Vec
{
public:
   float x, y, z;
};

One issue i ran into when i used a mix of structs and classes was when forward declaring them. Sometimes i would simply forget if Vec was a class or a struct. Similar with Color, Rect, Transform, etc. So i settled on using classes only, and if something needs to have all of it's members public, i simply set them as public and not protected/private.

 

Actually they are not pretty much identical they are identical, the code generated from them is exactly the same, a struct can have all the same things as a class.

 


Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, Mad Max

#9 Strewya   Members   -  Reputation: 1433

Like
4Likes
Like

Posted 21 January 2014 - 02:58 AM

Actually they are not pretty much identical they are identical, the code generated from them is exactly the same, a struct can have all the same things as a class.

 

The only difference is semantical regarding the default access rule for members (public vs private), which is why i said "pretty much identical", but yeah, the generated bytecode is the same.


devstropo.blogspot.com - Random stuff about my gamedev hobby


#10 blueshogun96   Crossbones+   -  Reputation: 914

Like
0Likes
Like

Posted 21 January 2014 - 02:59 AM

One thing I like to do with C++ is use structs as classes, but hide the class related code when C is accessing it.  This came in handy a few times for me.

struct whatever_t
{
#ifdef __cplusplus
public:
  void func1();
  int  func2(void*);
  byte func3(char, float);

public:
#else
//  struct _vtbl
//  {
    void (*func1)(struct whatever_t* This);
    void (*func2)(struct whatever_t* This, void*);
    void (*func3)(struct whatever_t* This, char, float);
//  }*vtbl;
#endif
  int var1, var2, var3;
};

#ifndef __cplusplus
 void whatever_func1(struct whatever_t* This);
 void whatever_func2(struct whatever_t* This, void*);
 void whatever_func3(struct whatever_t* This, char, float);
#endif

I once needed the functionality of classes, but at the same time, needed compatibility with C and C++.  This is how I did it.

 

EDIT: Minus the vtable.


Edited by blueshogun96, 21 January 2014 - 03:03 AM.

Follow Shogun3D on the official website: http://shogun3d.net

 

blogger.png twitter.png tumblr_32.png facebook.png

 

"Yo mama so fat, she can't be frustum culled." - yoshi_lol


#11 maxstrax   Members   -  Reputation: 84

Like
-6Likes
Like

Posted 21 January 2014 - 04:36 AM

I would also like to add that the compiler adds the operator= for any struct, by coping 1-1 all its fields, in a class you generally have to define your own class_name operator=(const class_name right); however there are certain conditions on which the C++ compiler may add that operator automatically (implicitly). If I recall correctly there is yet another difference, but I fail to remember it for the time being, my apologies!

Hope I helped a little



#12 NightCreature83   Crossbones+   -  Reputation: 2824

Like
5Likes
Like

Posted 21 January 2014 - 05:02 AM

I would also like to add that the compiler adds the operator= for any struct, by coping 1-1 all its fields, in a class you generally have to define your own class_name operator=(const class_name right); however there are certain conditions on which the C++ compiler may add that operator automatically (implicitly). If I recall correctly there is yet another difference, but I fail to remember it for the time being, my apologies!

Hope I helped a little

No you dont default copy constructor, default construct/destructor and default assignment operator are generated for a class, as soon as you write one of these the compiler will not generate a default one. There really is no difference between a class or a struct beyond the default access modifiers.


Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, Mad Max

#13 Aardvajk   Crossbones+   -  Reputation: 5981

Like
12Likes
Like

Posted 21 January 2014 - 06:21 AM

The other slight difference is the default inheritance type, if you omit the specifier when you inherit, but very few people ever seem to do that, or even use private inheritance much so it isn't a big deal.

 

class x : y { }; // default private inheritance

struct x : y { }; // default public inheritance

 

This and the default public/private access within the class are categorically the ONLY differences between struct and class as far as the compiler is concerned. However, it is a reasonably common convention to use structs to represent all-public, data-only types and classes for everything else.

 

Struct is really only included in C++ to support backward compatibility with old C code.



#14 JohnnyCode   Members   -  Reputation: 216

Like
-9Likes
Like

Posted 21 January 2014 - 08:39 AM

structs have an advantage over class of being properly serializable. As soon as your object definition does not contain an advanced datatype pointer, you are fully valid to write it as a struct, which fits for your vector class. But this all is just a question of code producing culture, nothing critical.

 

But as to vectors, I would recomend you to not write algebraic functions as members of a vector, but go for a globaly used Algebra object that takes vectors as inputs and returns, or, manipulates existing vectors for result.

 

 

 

 



#15 BitMaster   Crossbones+   -  Reputation: 4077

Like
14Likes
Like

Posted 21 January 2014 - 08:43 AM

structs have an advantage over class of being properly serializable.


This is completely false. Making something a struct does not automatically make somethings serializable by default. Making something a class does not automatically make is unserializable. In C++, the difference between class and struct is completely cosmetic: the default visibility and inheritance for a struct is public, private for a class.

See std::is_pod and related standard library constructs for questions regarding serializability.

#16 JohnnyCode   Members   -  Reputation: 216

Like
-2Likes
Like

Posted 21 January 2014 - 10:25 AM

 

This is completely false. Making something a struct does not automatically make somethings serializable by default. Making something a class does not automatically make is unserializable. In C++, the difference between class and struct is completely cosmetic

I did not say struct is serializable as an implicit fact. I said what it should be in my eyes - serializable. A single struct object, fully operative, can be resurected from its memory foot print. I repeat, not a fact, but an -expectation? Get me? At least this is my vision of a struct, if someone tends to write a struct with function members and all that. I do not expect a struct like this

 

struct vec2d

{

float x;

float y;

CAlg* m_pAlg;

 

void Init()

{

x=m_pAlg.Nod(x,y);

}

 

}



#17 JohnnyCode   Members   -  Reputation: 216

Like
-4Likes
Like

Posted 21 January 2014 - 01:16 PM

You have mentioned that struct/class difference in compiler interpretation is none. It is pure interpratation of a programmer, meaning, a programer should consider struct as a certain manifesting, towards a memory available object, as is. Interpratation and purpose of struct in area of profesional instruction writing still exists! You can(should) reproduce a struct from its own allocated memory- as a self encapsulated object on self memory (what is a definition of a "program" actualy as well). While a class like CSceneManager, is a wide memory object, not reproducible and dependant only on its allocated memory. A struct object is reproducible and fully operatible on its member functions, or outer functions expecting this object, from its allocated memory. From a programmer professioal view, if someone codes struct that depend on outer memory, is an unprofessional programmer who does not use instruction writing properly. You of course does not have to write a struct to achieve this, but if you encourage yourself to define object as a struct, be aware of not making yourself look like a noob.



#18 Aardvajk   Crossbones+   -  Reputation: 5981

Like
9Likes
Like

Posted 21 January 2014 - 01:24 PM

You have mentioned that struct/class difference in compiler interpretation is none. It is pure interpratation of a programmer, meaning, a programer should consider struct as a certain manifesting, towards a memory available object, as is. Interpratation and purpose of struct in area of profesional instruction writing still exists! You can(should) reproduce a struct from its own allocated memory- as a self encapsulated object on self memory (what is a definition of a "program" actualy as well). While a class like CSceneManager, is a wide memory object, not reproducible and dependant only on its allocated memory. A struct object is reproducible and fully operatible on its member functions, or outer functions expecting this object, from its allocated memory. From a programmer professioal view, if someone codes struct that depend on outer memory, is an unprofessional programmer who does not use instruction writing properly. You of course does not have to write a struct to achieve this, but if you encourage yourself to define object as a struct, be aware of not making yourself look like a noob.

 

I have never come across this expectation among professionals. Not really sure where you are getting it from.

 

struct keyword exists in C++ purely to allow backward compatibility with older code. POD is a very different thing to struct as has been pointed out and the fact that something is implemented as a struct should in no way be taken as an indication that it is possible to serialize/restore it from its memory footprint.

 

What about a struct containing a pointer to memory it doesn't own, such as a node in a linked list in C? That can't be serialized and recreated from its memory footprint. Does that mean it is noobish? Strange idea.



#19 cozzie   Members   -  Reputation: 1611

Like
1Likes
Like

Posted 21 January 2014 - 01:25 PM

Thanks for all the replies and help.
For now I'm convinced that for vector3 I'll keep the struct and for functions that don't actually change or return "this" make free functions within the same header/cpp files for keeping code maintainable. Basically that means only operator functions within the struct, and maybe normalize since it directly changes the members.

#20 Hodgman   Moderators   -  Reputation: 30380

Like
4Likes
Like

Posted 21 January 2014 - 03:11 PM

One thing that I think that Johnny is trying to say is that it's a common convention for struct to be used for POD types, and class to be used for non-POD types.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS