Re: C-style unit -> C++ class, implementation function / structure issue
On Jul 12, 9:14 pm, "Alf P. Steinbach" <al...@start.no> wrote:
* James Kanze:
[...]
I defined the struct in the .cpp file, since only the implementation
functions in the .cpp file used it. The struct was not required for
any interface functions, so it didn't have to exist in the .h file.
In other words, the compilation firewall (pimpl) idiom. You can
do exactly the same in C++.
Yes, I also suggested PIMPL, plus a special case (singleton) where no
dynamic allocation is required.
However, the OP is very very vague about his code, and PIMPL isn't
necessarily required.
Yes. I wasn't too sure myself what he meant. Two possibilities
occured to me: one was that the struct was for some internal
use, used in only within functions. But in that case, what's
the problem. It seems obvious to me that you can do exactly the
same thing in C++ as in C. A member function is certainly free
to use non-member, locally defined types. (I regularly do this
for classes which need to parse their data from strings, for
example. The structures which support parsing are defined in an
anonymous namespace in the source file, and aren't even named in
the header.)
The other possibility was the classical C idiom for
"implementing" private data: in the header file, you forwarded
declared the class (without defining it), and declared a number
of functions, all of which took a pointer to the class as an
argument. Only these functions, of course, need to know the
definition of the class, since client code only manipulates a
pointer. And I think you'll agree that this is really the same
thing as the pimpl idiom, even if C programmers don't use that
name, and it was widespread in C long before C++ became popular.
(I was using it in the mid 1980's.)
In the end, you have a choice:
-- You can hide the data structure completely. Client code
cannot possibly access it, because it doesn't even know the
structure, and the structure can change without requiring
recompilation of the client code. To do this, however,
means that the actual data must be dynamically allocated
(ignoring singletons and the like), and that there will
often be an additional level of indirection. In C++, at
least, deallocation can be handled automatically by means of
the destructor; in C, it's up to the client code to
explicitly call destruct.
-- You can avoid the need for dynamic allocation, and allow the
actual data to be on the (client) stack. In this case, the
structure of the data must be known to the compiler of the
client code, if only so that it knows how many bytes to
allocate on the stack. Changing the data means recompiling
the client code. And in C, this effectively means that all
of the data are "public"; the client code has direct access
to them. "Best practice" in C consists of defining a struct
and a set of functions which manipulate it, and crossing
your fingers that no client code manipulates it other than
with your functions. At the very least, C++ means that you
don't have to cross your fingers. (C++ also has a few other
features, that are sometimes useful, but they're not that
important; just icing on the cake, so to speak.)
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34