class vs struct mindset
Posted: October 16th, 2017, 7:01 pm
When I first started learning C++ I had no idea if there was a difference between class and struct. I spent a few hours searching google and reading stackoverload posts and came to the understanding that with the exception of access they are the same thing. Class members ( variables ) and methods ( functions ) are always private unless explicitly made public using public: before a section of members and methods while struct members and methods are always public by default.
Another thing I started to wonder is why have these two things that are so similar in the language and after a bit more looking around I noticed a pattern of usage for the two. Classes always seemed to be used when there were functions involved while structs were mostly used for POD ( plain ole data ). This seemed logical to me for some time and still to this day. When I say plain ole data, I'm thinking of just a grouping of variables that doesn't have behavior and only controls the behavior of another object. For instance, instead of having a function with a lot of parameters, you'd fill in a struct and pass the struct. This is pretty common practice in the DirectX and Windows APIs. Not to mention the phrase 'data structure' does not make me think of a class, but it does make me think of a struct.
I kind of believe that this thinking is also a throwback to C where struct was only able to have data, functions were not allowed. Now I didn't start with C technically. Chili did start by teaching C in his original series as a build up to C++, but he did now really push any C coding idioms. With C++, since structs don't have the same restrictions with struct and they do allow member functions, I see no reason not to add constructors and other functions that might be useful.
For those that have gotten to experiment with inheritance, you know that when you inherit a class you must specify what type of inheritance you want; public, protected or private. Most of the time you end up writing public: but with structs since they are public by default, you can omit the type of inheritance.
Another thing that I've been considering for a while now is how to structure my class layout. Since they are private by default, do I put the private data at the top to avoid having to type private before the private members or methods?
I've seen this approach quite a bit and it is logical. Class members and methods are private by default, so put the private stuff first. I do have a problem with this though. If I want to use your class in my own code and if your class is quite lengthy I have to hunt down the public interface functions which are all the way at the bottom. I don't need to know about the functions and data I don't have access to, so why list them first?
Currently, I tend to put the public stuff first so anyone looking to see externally callable functions will be able to find them more easily, including myself. This does require then I now put public: before the public interface and explicitly mark which functions and data members I want to be private. With the mindset of wanting to put default access members and/or methods at the top and the mindset of wanting to put the public interface near the top, it stands to reason for most cases one should prefer using struct instead of class as their go to data structure.
Public interface is at the top. Struct is public by default so I don't have to specify public at the beginning every time, and now I only have to explicitly specify what I want private. I think this is probably what I'm going to start doing from now on. I will have to get over my mindset of struct being reserved for strictly data containers with no behavior with classes have behavior and state. My new mindset will have to be, which makes code more reasonable.
There is a coding idiom of creating interfaces, which deal strictly with inheritance. An interface in this instance is a group of function signatures without definitions and cannot have data members.
The name "interface" means something you interact with so there is no need for private or protected methods. For that reason, a struct is a much nicer fit than class. The concrete struct of Person can have private methods, maybe a helper function that concatenates the first and last name and returns it to GetFullName for instance.
Anyway, just thought I'd try invoking a discussion and make a logical argument for defaulting to struct over class and challenge mindsets of experienced programmers here on the forum.
Another thing I started to wonder is why have these two things that are so similar in the language and after a bit more looking around I noticed a pattern of usage for the two. Classes always seemed to be used when there were functions involved while structs were mostly used for POD ( plain ole data ). This seemed logical to me for some time and still to this day. When I say plain ole data, I'm thinking of just a grouping of variables that doesn't have behavior and only controls the behavior of another object. For instance, instead of having a function with a lot of parameters, you'd fill in a struct and pass the struct. This is pretty common practice in the DirectX and Windows APIs. Not to mention the phrase 'data structure' does not make me think of a class, but it does make me think of a struct.
I kind of believe that this thinking is also a throwback to C where struct was only able to have data, functions were not allowed. Now I didn't start with C technically. Chili did start by teaching C in his original series as a build up to C++, but he did now really push any C coding idioms. With C++, since structs don't have the same restrictions with struct and they do allow member functions, I see no reason not to add constructors and other functions that might be useful.
For those that have gotten to experiment with inheritance, you know that when you inherit a class you must specify what type of inheritance you want; public, protected or private. Most of the time you end up writing public: but with structs since they are public by default, you can omit the type of inheritance.
Code: Select all
class base {};
class derived : public base{};
vs
struct base{};
struct derived : base{};
Code: Select all
class MyClass
{
int age = 42;
std::string first, last;
public:
int GetAge()const;
std::string GetFirstName()const;
std::string GetLastName()const;
std::string GetFullName()const;
};
Currently, I tend to put the public stuff first so anyone looking to see externally callable functions will be able to find them more easily, including myself. This does require then I now put public: before the public interface and explicitly mark which functions and data members I want to be private. With the mindset of wanting to put default access members and/or methods at the top and the mindset of wanting to put the public interface near the top, it stands to reason for most cases one should prefer using struct instead of class as their go to data structure.
Code: Select all
struct MyClass
{
int GetAge()const;
std::string GetFirstName()const;
std::string GetLastName()const;
std::string GetFullName()const;
private:
int age = 42;
std::string first, last;
};
There is a coding idiom of creating interfaces, which deal strictly with inheritance. An interface in this instance is a group of function signatures without definitions and cannot have data members.
Code: Select all
// This would be considered an interface. Only function signatures, no data members allowed.
struct IPerson
{
virtual int GetAge()const = 0;
virtual std::string GetFirstName()const = 0;
virtual std::string GetLastName()const = 0;
virtual std::string GetFullName()const = 0;
};
// This would be an implementation of the IPerson interface.
struct Person : IPerson
{
int GetAge()const override;
std::string GetFirstName()const override;
std::string GetLastName()const override;
std::string GetFullName()const override;
private:
std::string ConcatName()const;
// Private not needed here because everything below ConcatName would be private.
// Only used as a separator between private methods and private members
private:
int age = 42;
std::string first, last;
};
Anyway, just thought I'd try invoking a discussion and make a logical argument for defaulting to struct over class and challenge mindsets of experienced programmers here on the forum.