Question

I have some code in C, that uses incomplete structs this way ( simplified example ):

something.h

struct something;

struct something *new_something();
int work_a(struct something *something);
int work_b(struct something *something, const char *str);
void free_something(struct something *something);

somecode.c

int some_function()
{
    struct something *something;
    int x;

    something = new_something();
    x = work_a(something);
    free_something(something);
    return x;
}

I was thinking, I'm basically doing C++ here, why not try write it in C++ . The question is ( I'm new to C++ ), how do I achieve the same in C++ ? If I try to add declare a member function of an incomplete class, I get

error: incomplete type 'something' named in nested name specifier

from clang. By writing the complete class in the header, this would lose the whole point of data hiding, and changing private vars in the class would force every file including "something.h" to recompile, which I think is not needed here. I don't need the files using "something.h" to know the size of this struct / class, I'm usually fine with having just a pointer. I suspected it should look like this:

 class Something;

 Something::Something();
 Something::~Something();
 int Something::work_a(int x);

this way I could write the same thing I did in C, only shorter, and even cleaner. Any C++ coder out there wishing to enlighten this mortal C coder?

Was it helpful?

Solution

Take a look at this article: Hiding Implementation Details in C++. It should get you pointed in the direction you are looking. Note that inheritance is being used to accomplish the goal. Also understand that in C++, a struct is a class with all members having public access (includes functions, constructors, and destructors). At a minimum, the interface has to be declared a class, then inherit from that publicly in the now hidden class implementation inside the cpp file (not another header file).

On the Pimpl design pattern, check out this Stack Overflow article: pimpl idiom vs. bridge design pattern. It should also help.

OTHER TIPS

One way to achieve this is through the Pimpl design pattern where you have a pointer to some private struct/class that only your implementation knows about. Your private functions use the pointer and in theory it can be mostly inlined.

When you allocate memory with new statement the compiler has to know how much data space to allocate. The data size of Something has be seen by the compiler before you can use new to create a Something instance.

Use something like this in Something.h

class Something {
public:
 Something();

private:
 struct HiddenData;
 HiddenData* m_pHidden;
};

Use something like this in Something.cpp

struct Something::HiddenData {
int a;
int b;

};

Something::Something() : m_pHidden(new HiddenData()) {
 m_pHidden->a = 1;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top