Search code examples
c++structdata-members

Putting data members inside a struct?


I'm bringing some old unmaintained software up to date, and I've noticed a peculiar pattern that I haven't been able to adequately explain.

The code in question is written in C++. Normally when I see data members, they exist inside the class declaration as public or private members. In the code I'm currently working with, nearly every class stores the data members inside an additional struct, like so:

struct MyClassData {
    int foo;
    int bar;
};

class MyClass {
    MyClassData classData;

public:
    void doFoo();
    void doBar();
    void doBaz();
};

Unfortunately the original maintainer of this code is unreachable. Every single class (there's about a hundred of them) all do this though. I can't figure out why, since the MyClassData struct is never used anywhere other then at the top of the class declaration.

Is there any particular reason why someone would choose to layout their C++ classes in this manner? I understand there are reasons for wanting and using a struct as a data member, but what I don't understand is why you'd want to stuff all your data members inside a single struct like this, and never doing anything else with that structure. I suppose it might remove any ambiguity as to what you're accessing within your methods and how (since everything will need to go through classData first), but beyond that, I dunno. I'm wondering if there's a technical reason for this that I haven't yet uncovered.


Solution

  • There's no particular technical constraint satisfied by this uncommon pattern.

    I can guess at the author's intentions (though, ultimately, you would have to ask them):

    1. An over-fed obsession with and misunderstanding of the notion of "encapsulation"
      ("this way all the data is kept together!")

    2. Separate serialisation code can reference the type in isolation without having to be a friend of MyClass.

    3. MyClassData is an aggregate (at least in this example, where all its members are int) allowing you to initialise it in certain convenient ways. But, if you're always going to have it as part of a MyClass, I don't see how that's a benefit you can put to any meaningful use.

    As an aside, personally I'd have made that a nested detail class if anything. As it is here, it's very easy to have a MyClassData without a MyClass, and what's the point of that? Not very clear at all.

    In the absence of any explanatory comments or documentation, and given that the original author is unreachable, I wouldn't worry too much about abiding by this pattern. There's no strong reason I can see to stick to it, beyond the principle of keeping your codebase consistent or avoiding creating a ton of refactoring work for yourself.