C++ Some of you won't like this: struct vs. class

This is something I do that I am sure will drive some people nuts.

In C++, struct and class are basically synonyms. The only difference is class defaults to private members while struct defaults to public members.

You might expect something like this:

Code:
class Object
{
    // private bits go here.

public:
    int get_Value() const;
    void member1();
    void member_function2(const char *arg);
    Object(); // constructor
};

Instead I do this:

Code:
struct Object
{
    int get_Value() const;
    void member1();
    void member_function2(const char *arg);
    Object(); // constructor

private:
    // private bits go here.

};

Why? I like placing all of the public members at the top of the class. I can peek at the header file to see the public API - usually without the need to scroll down. Since struct makes members public by default, I don't need to waste a line with a public: clause.

Feel free to applaud or (more likely) object.
 
For a large class, you might see alternating public/protected/private clauses. To me, this looks messy but the author might be trying to convey how the members relate to each other (or is expected to list them in alphabetical order).
 
The Artistic Style source formatter (https://astyle.sourceforge.net/) eliminates the need for arguments about indentation and brace placement, by letting you reformat a program into any of 15 popular brace and indentation styles (or you can make you your own style).

Perhaps the world needs a deeper formatter that will deal with various quirks such as class vs struct.

BTW, having worked with a crew that used a random style for braces and indentation (a bunch of old mainframe assembler programmers who had been told to start coding in C, and were doing it without much enthusiasum), I almost think it would been nice to have artistic style as part of the check-in process for changes. Luckily for me, I retired from that group almost a decade ago, so it's not my problem.
 
While we are talking about style and readability, I need to put in a good word for Large Scale C++: Process and Architecture, Volume 1, by John Lakos. (The previous edition, which I had, was called just Large Scale C++).


It has a lot of good information about coding practices that will make your life easier when your project contains hundreds of modules, things like ways to keep simple changes from causing everything to get recompiled.
 
This is something I do that I am sure will drive some people nuts.
The software engineering field is full of people who get driven nuts by small things that make little difference. Many of those people join the "coding style" committees of their respective work places, and then turn their own preferences into the law. Enforcement of these preferences then leads to a culture of rigid code reviews, lots of effort being put into checker and formatter tools, people looking at style rather than substance. Instead of writing good software (bug free, easy to understand and therefore fix and enhance in the future) they write software that matches the coding rules perfectly. The whole thing becomes a culture of "virtue signaling" instead of doing the right thing.

In C++, struct and class are basically synonyms. The only difference is class defaults to private members while struct defaults to public members.
Yes, that is an unfortunate legacy of the history of C++. Personally, I would prefer if only one of the keywords "class" and "struct" existed. I also don't think that relying on defaults is a good idea, since those can easily be overlooked or forgotten, and I prefer my code to be more explicit.

Having said that, I use the following convention (which also matches the coding style of a big former employer): A struct has only data in it, and no methods. Everything in a struct is public. If there are compiler-generated methods, they will be trivial, and don't need to be mentioned.

Why? I like placing all of the public members at the top of the class. I can peek at the header file to see the public API - usually without the need to scroll down.
Here's my convention, YMMV. The "big four" (default constructor, copy constructor, operator= and destructor) always go at the very top, in that order. If they are not public, it needs to be commented why not. If compiler-generated versions are used, the prototype for them is still in the source, commented out, with the comment showing that we're using the compiler generated one.

After that, the other methods are ordered roughly by importance to the user of the class. Which usually means the public ones come first, then protected, then internal implementation helpers and private. Data comes last. But for large classes (with say more than a dozen methods in them), it may make sense to group them by functionality. For example for the purple flying elephant class, first everything relating to its color (in that section ordered public/protected/private), then everything about locomotion and flying (same order), then nutrition and health maintenance. If that is done, but a comment at the top explaining the order, and where to find things: public functions for brushing teeth will come after all the functions (public and private) for flapping the ears and steering the flight path.

The order of things in the .C file exactly matches the order in the .h file. I try to have different comments in the two files: The header file explains how to use this class; the implementation file how it works internally. But that is often not a clear distinction (since design decisions usually affect both), so there will be some repetition in the comments. This is one of the reasons why I prefer languages such as Java and Python where a source module is described in a single file.

In general, I hate overuse of the DRY principle. Indeed, having the same text (whether code, comment, or design document) in two places is a maintenance problem, and should be avoided. But having a comment somewhere that the answer can be found in another place is helpful, even if it offends DRY bigots.

In the real world, source files tend to get long. The theory of "files under 100 lines, ideally 24 lines, and tiny commits" doesn't work in the real world, as it fragments coherent pieces of code and changes into grains of sand that are hard to understand. Given that source files are long, one needs a convention for how to group them into sections, just like big books are grouped into volumes, chapters, sections, paragraphs and so forth. For example:
C:
// ==========================================================================
// THIS IS A BIG CHAPTER. IT WILL BE LONG. IT EXPLAINS THE LIFE OF A PENGUIN.

// --------------- This is a section heading. How a penguin moves.
// This code assumes that house and hole have been initialized above.

// The next few lines of code implement the penguin pattern:
penguin* pengy = new EmperorPenguin(...);
if (polar_bar.near(pengy)) {
    pengy.hide(hole)
}

But the really important part is this: When I work in a group of people, we will all agree on the conventions. For example, my colleagues and I all know that "long line of equal signs going all the way across the screen means a new and long chapter of code and comments are starting here". And they know that we don't use Hungarian notation: the fact that the name of my penguin starts with "p" is not because it is a pointer, but because that's its name.

Feel free to applaud or (more likely) object.
Nice pun.
 
Having said that, I use the following convention (which also matches the coding style of a big former employer): A struct has only data in it, and no methods. Everything in a struct is public. If there are compiler-generated methods, they will be trivial, and don't need to be mentioned.
Yep; and keeping to this definition makes portability between C++ and C easier (think libraries that you have no control over useage).
 
Why? I like placing all of the public members at the top of the class.
Completely agree.

It also has another benefit. It isn't just members that are public by default with a struct. Inheritance is also public. So you can avoid excess noise (C++ is verbose enough).

If Employee is defined as a struct rather than class, you can skip the extra public:

Code:
struct Manager : /*public*/ Employee
{ };

Its also easier to pass C++ structs through C layers.
 
ADD 1 TO COBOL GIVING COBOL. Another version of the same joke.

A few months ago, I downloaded some Cobol compiler for fun, and spent an evening with a single glass of wine writing an 80-line program, and got it to work. It was fun, but I'm so glad I have better tools available now. It's like building a small wooden thing using no power tools, only hand saws, planes and chisels. While it can be done, it's not productive, but fun art and craftsmanship.
 
Back
Top