C-style unit -> C++ class, implementation function / structure issue

J

Jason Doucette

I am converting a C-style unit into a C++ class. I have an
implementation function that was defined in the .cpp file (so it was
hidden from the interface that exists in the .h file). It uses a
structure that is only needed by the implementation, so it were
declared in the .cpp file, as well.

Now, when converting this into a class, the class definition exists in
the .h file, since it's required by the interface. The implementation
functions go under a "private" access specifier, so they are moved
from the .cpp file into the .h file. But, it needs access to the
above mentioned structure. It seems I must include the structure in
the .h file, making it publicly accessible!

Since no public member functions make use of the structure, I know
that no one can do anything with it, so everything is ok. But it just
seems UGLY to make something publicly accessible when it should be
hidden in the implementation.

Is there a way to achieve this?

Jason
 
A

Alf P. Steinbach

* Jason Doucette:
I am converting a C-style unit into a C++ class. I have an
implementation function that was defined in the .cpp file (so it was
hidden from the interface that exists in the .h file). It uses a
structure that is only needed by the implementation, so it were
declared in the .cpp file, as well.

Now, when converting this into a class, the class definition exists in
the .h file, since it's required by the interface. The implementation
functions go under a "private" access specifier, so they are moved
from the .cpp file into the .h file. But, it needs access to the
above mentioned structure. It seems I must include the structure in
the .h file, making it publicly accessible!

Since no public member functions make use of the structure, I know
that no one can do anything with it, so everything is ok. But it just
seems UGLY to make something publicly accessible when it should be
hidden in the implementation.

Is there a way to achieve this?

See PIMPL idiom. Generally it involves dynamic allocation. For hazards
of avoiding dynamic allocation for PIMPL, see the relevant GOTW.

However, it this is singleton you can do it like

//---------------- .h file
struct SomeSingleton
{
virtual formatMyDisks() = 0;
static SomeSingleton& instance();
};

//---------------- .cpp file
#include "the.h"
namespace
{
struct Impl: SomeSingleton
{
virtual formatMyDisks() { /* Yes! */ }
};
}

SomeSingleton& SomeSingleton::instance()
{
Impl theSingleton;
return theSingleton;
}

Hth.,

- Alf
 
K

Kai-Uwe Bux

Jason said:
I am converting a C-style unit into a C++ class. I have an
implementation function that was defined in the .cpp file (so it was
hidden from the interface that exists in the .h file). It uses a
structure that is only needed by the implementation, so it were
declared in the .cpp file, as well.

Now, when converting this into a class, the class definition exists in
the .h file, since it's required by the interface. The implementation
functions go under a "private" access specifier, so they are moved
from the .cpp file into the .h file. But, it needs access to the
above mentioned structure. It seems I must include the structure in
the .h file, making it publicly accessible!

Since no public member functions make use of the structure, I know
that no one can do anything with it, so everything is ok. But it just
seems UGLY to make something publicly accessible when it should be
hidden in the implementation.

It appears that you are confusing header files and documentation. That
information about class layout (including private members) is put into
header files just goes to show that the intended reader of a header file is
the compiler, not your fellow programmer.

What is an implementation detail is not decided by whether it goes into a .h
or into a .cpp file.

Is there a way to achieve this?

For private, non-virtual member functions, you can turn them into global
friend functions taking an additional pointer-to-class parameter. Every
call would then explicitly have to pass the this-pointer. That is even more
ugly.

For private data-members, the compiler needs to know about them anyway for
allocation purposes.

I also have the vague recollection that the Pointer-to-Implementation idiom
may provide a way around your problem.


Best

Kai-Uwe Bux
 
J

Jason Doucette

See PIMPL idiom. Generally it involves dynamic allocation.

I found a pretty decent rundown of it here:
http://www.gamedev.net/reference/articles/article1794.asp

I see that it requires dynamic allocation, and an extra dereference
for any of these functions. Since I am developing a performance
application, this is unacceptable.

For hazards
of avoiding dynamic allocation for PIMPL, see the relevant GOTW.

You mean http://www.gotw.ca/gotw/028.htm ?


I guess, the real question is: Is there a more proper way than what I
am already doing? I don't want to achieving the end result at any
cost. If it's more complicated to do this than it would be if left as-
is, then I'll leave it as-is. It's just a simple annoyance in C++,
among many with interfaces/implementations <sigh>, but if C++ wants it
to be this way, then I guess it should be this way. I won't try and
fight for *any method possible* to get my implementation structures
defined in the .cpp, if it requires great (or even moderate)
complexity.

I should have rephrased my question more accurately.

Thanks for your reply,
Jason
 
J

Jason Doucette

It appears that you are confusing header files and documentation. That
information about class layout (including private members) is put into
header files just goes to show that the intended reader of a header file is
the compiler, not your fellow programmer.

I am not confusing header files and documentation. Allow me to
explain:

I have a structure that only the implementation of the class uses.
But, since C++ forces the entire class to be defined in the .h file,
then all implementation functions must also be defined in the .h
file. Files that #include the .h file can still only 'see' the
interface, so that's fine. But, as a result, these implementation
functions that use implementation-only structures force these
structures to be defined in the .h file, making them visible to all
files that #include the .h file.

Ok, I just solved my issue by talking through it: I just have to make
my structure itself defined within my class's private section... of
course. I don't believe I've ever done that, so I didn't immediately
think of it as a possibility.

Thanks for your replies, they've been helpful.

Jason
 
J

James Kanze

I am not confusing header files and documentation. Allow me to
explain:
I have a structure that only the implementation of the class uses.
But, since C++ forces the entire class to be defined in the .h file,
then all implementation functions must also be defined in the .h
file. Files that #include the .h file can still only 'see' the
interface, so that's fine. But, as a result, these implementation
functions that use implementation-only structures force these
structures to be defined in the .h file, making them visible to all
files that #include the .h file.

I'm not sure I understand. How did you get by in C without
defining the struct in the header? You can wrap exactly the
same technique in a class.
 
J

Jason Doucette

I'm not sure I understand. How did you get by in C without
defining the struct in the header? You can wrap exactly the
same technique in a class.

(I was using a C++ compiler, so my original code wasn't technically
plain C code... I was using C++ without classes. I was using C-style
units of functions, where the implementation existed all in the .cpp
file, and the interface was visible in the .h file)

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.

My issue is that I didn't want to move the struct into the .h file
when I converted this 'unit' into a C++ class. But, I now realize I
can put the struct in the .h file, under the class's private section,
and it'll be hidden from the interface. All is well.

Thanks,

Jason
 
J

James Kanze

(I was using a C++ compiler, so my original code wasn't technically
plain C code... I was using C++ without classes. I was using C-style
units of functions, where the implementation existed all in the .cpp
file, and the interface was visible in the .h file)
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++.
My issue is that I didn't want to move the struct into the .h file
when I converted this 'unit' into a C++ class. But, I now realize I
can put the struct in the .h file, under the class's private section,
and it'll be hidden from the interface. All is well.

Yes. C++ gives you the choice; C didn't.
 
A

Alf P. Steinbach

* James Kanze:
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.

For example,

//------------------- the.h

#ifdef THE_H
#error On the usenet, we strive to minimize typing.
#endif
#define THE_H

class SillyClass
{
private:
struct Foo;
void get( Foo& );
public:
void doThings();
};


//------------------- the.cpp

#include "the.h"

struct SillyClass::Foo
{
char data[100000];
};

void SillyClass::get( Foo& fooData ) { ... }

void SillyClass::doThings()
{
Foo fooData;
get( fooData );
...
}
 
J

Jason Doucette

(I was using a C++ compiler, so my original code wasn't technically
In other words, the compilation firewall (pimpl) idiom. You can
do exactly the same in C++.

I didn't think my issue was the Pimpl Idiom... but I don't know
exactly what Pimpl is about, so I could be wrong. I thought Pimpl was
to allow the implementation to change without any visible effects in
the interface, and thus saving compilation times.

My issue is merely that I don't want an implementation-only structure
visible at all. And this entire thread was rather unneeded, since C++
does have a way to hide an implementation structure from being visible
-- just define it in the class itself as private! I should have known
this.

Yes. C++ gives you the choice; C didn't.

Actually, in C, I had the structure declared in the .cpp file, so it
wouldn't appear in the interface. I could change the .cpp file all I
wanted, and since the .h file never changed, all was well.

Only in C++ does the changes to the implementation all of a sudden
require a recompile for any 'users' of the class, since they include
the .h file which you are changing.

Thanks for your thoughts,

Jason
 
J

Jason Doucette

However, the OP is very very vague about his code, and PIMPL isn't
necessarily required.

I am sorry, it is no intention of mine to be vague. I was under the
impression that I gave as many details as I could to explain my exact
situation. Perhaps we're on two different pages. I am not sure if
Pimpl applies to my concern. I merely was unaware that I could define
structures inside of a class definition, and once I clued in that it
was possible, it solved my concern. I had no issues about compilation
times, etc.

Jason
 
J

James Kanze

I didn't think my issue was the Pimpl Idiom... but I don't know
exactly what Pimpl is about, so I could be wrong. I thought Pimpl was
to allow the implementation to change without any visible effects in
the interface, and thus saving compilation times.
My issue is merely that I don't want an implementation-only structure
visible at all. And this entire thread was rather unneeded, since C++
does have a way to hide an implementation structure from being visible
-- just define it in the class itself as private! I should have known
this.

It wasn't clear, but I presumed that the C idiom you were
talking about was to forward declare the struct in your header,
to pass a pointer to it to all of the functions, and to only
define it in the source files that used it. That's exactly what
the compilation firewall idiom does in C++. In both C and C++,
of course, it requires that the actual data be dynamically
allocated (or static, if there is only one of them). If that's
not the case, then I don't know what in C you are trying to map
into C++.

For the rest, of course, declaring member types (private or
otherwise) is pretty much standard C++.
Actually, in C, I had the structure declared in the .cpp file, so it
wouldn't appear in the interface. I could change the .cpp file all I
wanted, and since the .h file never changed, all was well.

In which case, you can do exactly the same in C++. (I tend to
do it a lot, in fact.)
Only in C++ does the changes to the implementation all of a
sudden require a recompile for any 'users' of the class, since
they include the .h file which you are changing.

Not if you do it the same way you do in C. As I said, in C++,
you have the choice; both solutions work. Typically, declaring
more in the header will result in slightly faster execution
times, but more compiler dependencies. The smaller and simpler
the class, the more the difference in execution times will be
noticeable, and for something like complex, where the data
structure is more or less predefined and won't ever change, but
which is likely to be used in some tight loops, the C++ solution
definitly has an advantage (and in fact, in C, you'd certainly
declare the struct in header as well, even if it means that
anyone can actually access the data directly). For larger, more
complex objects, the time difference quickly becomes
negligeable, however, and in large projects (say, from a million
LOC up), the compilation firewall idiom is almost an automatism.
 
J

James Kanze

* James Kanze:

[...]
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.)
 
J

Jason Doucette

It wasn't clear, but I presumed that the C idiom you were
talking about was to forward declare the struct in your header,
to pass a pointer to it to all of the functions, and to only
define it in the source files that used it.

Oh right... because the structure is passed in as a pointer, the class
definition doesn't need to know what the structure actually is. It
just needs to be forward declared. And the definition can still exist
in the .cpp file. I'll give that a shot. I knew you could do this
with classes, and in fact I just did so recently, but I wasn't
thinking that you could with structs, even though they are practically
identical in C++, so I should have known.

Now we're on the same page! :) Thanks...

That's exactly what
the compilation firewall idiom does in C++.

Yes, because now I can change the implementation (structure and the
functions that use it) without having to change the .h file. Right?

In both C and C++,
of course, it requires that the actual data be dynamically
allocated (or static, if there is only one of them).

Not necessarily, the functions can deal with an address of a static
instance of the structure. But, this is besides the point. I think
you naturally assumed that any structure I was talking about would be
passed in as a pointer, and of course, you were right.

In which case, you can do exactly the same in C++. (I tend to
do it a lot, in fact.)

Right, and now I understand that you can. Without forward
declaration, you cannot, and that's where I was stuck.

Not if you do it the same way you do in C. As I said, in C++,
you have the choice; both solutions work.
Right.


Typically, declaring
more in the header will result in slightly faster execution
times, but more compiler dependencies.

Fast execution times? Why is that?
The smaller and simpler
the class, the more the difference in execution times will be
noticeable, and for something like complex, where the data
structure is more or less predefined and won't ever change, but
which is likely to be used in some tight loops, the C++ solution
definitely has an advantage (and in fact, in C, you'd certainly
declare the struct in header as well, even if it means that
anyone can actually access the data directly).

My data structures won't change often, and I'm writing a performance
application, so I want speed where I can get it for free, for sure. I
don't see how either method affects final execution times -- and if
that's the case (the speed is the same in both cases), then my only
concern is compilation times, which I would love to speed up.

For larger, more
complex objects, the time difference quickly becomes
negligible, however, and in large projects (say, from a million
LOC up), the compilation firewall idiom is almost an automatism.

I can imagine. I am not there, but my LOC is high enough that
compilation is a concern. One thing that would help is if both CPUs
were used in the compile process; there's apps out there that'll do
that, and I should take a look at some of them.

Thanks for your help, James.

Jason
 
J

Jason Doucette

[snip] 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 thought the same, until I realized C++ forced me to declare my
private member functions in the .h file, where as in C, I declared my
implementation functions in the .cpp file. And this was ok, until
those functions had to use this internal-use-only structure. But, as
you've shown me, a forward declaration allows me to define the
internal-use-only structure in the .cpp, but be referenced in the .h
file in the private member function declarations. Problem solved!
Tested and confirmed. :)
-- 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.

Ah, now I get why you say dynamic allocation. You are speaking about
a class data member. In my case, the implementation uses a structure,
but it is only used internally in a few functions, so it is a function
local variable. It is dynamically allocated, but it could be exist
statically (although that wouldn't make sense if it were large, since
it'd be on the stack, and that's a no-no).

Jason
 
B

BobR

Jason Doucette said:
Oh right... because the structure is passed in as a pointer, the class
definition doesn't need to know what the structure actually is. It
just needs to be forward declared. And the definition can still exist
in the .cpp file. I'll give that a shot.

"Cheshire cat" ( 'handle class' ).
[ a 'loose' example. <G> ]

// --- auto.h ---
#include <ostream>

class Car{ public:
void initialize( size_t );
void cleanup();
void Print( std::eek:stream & );
private:
struct car; // the "Cheshire cat"
car *theCar; // this is all the user sees
};
// --- auto.h --- END

// --- auto.cpp --- // distribute as lib, .so, or ?
#include "auto.h"

struct engine{
double weight;
double cubic_capacity;
};
struct transmission{
double weight;
unsigned type;
};

struct Car::car{
engine eng;
transmission trans;
size_t serial_no;
car() : serial_no(0){
eng.weight = 470.19;
eng.cubic_capacity = 327;
trans.weight = 105.7;
trans.type = 2;
}
car( size_t serl ) : serial_no( serl ){
// or, move all this to engine, transmission Ctors
eng.weight = 470.19;
eng.cubic_capacity = 327;
trans.weight = 105.7;
trans.type = 2;
}
};

void Car::initialize( size_t Serial ){ // or in Car::Car() Ctor.
theCar = new car( Serial );
}

void Car::cleanup(){ delete theCar; }
// example. Better to do this in Car destructor so the user can't forget!

void Car::print( std::eek:stream &out ){
out<<"\ntheCar->serial_no="<<theCar->serial_no;
out<<"\ntheCar->eng.weight="<<theCar->eng.weight;
out<<"\ntheCar->eng.cubic_capacity="
<<theCar->eng.cubic_capacity;
out<<"\ntheCar->trans.weight="<<theCar->trans.weight;
out<<"\ntheCar->trans.type="<<theCar->trans.type;
out<<std::endl;
return;
}
// --- auto.cpp --- END

// --- main ---
#include <iostream>
#include "auto.h"

int main(){
Car myCar;
myCar.initialize( 4032005 );
myCar.Print( std::cout );
myCar.cleanup();
return 0;
} // main()
// --------------------------
This is an old example I had laying around. Add constructors instead of
using 'initialize()' (that's part of the 'loose', IMHO).

Is that what you were/are doing?
I knew you could do this
with classes, and in fact I just did so recently, but I wasn't
thinking that you could with structs, even though they are practically
identical in C++, so I should have known.

struct Base{ int number; virtual ~Base(){} };
class Derived : public Base{ /* .... */ }; // no problem
 
B

BobR

BobR wrote in message...
"Cheshire cat" ( 'handle class' ).
[ a 'loose' example. <G> ]

// --- auto.h ---

Dang, meant to mention 'inclusion guards' here, but, I'll bet you know that.
 
J

James Kanze

[...]
Yes, because now I can change the implementation (structure and the
functions that use it) without having to change the .h file. Right?

Right. The idiom is far from new (although the name pimpl is
fairly recent). In C, it was more often used as a means of
making the structure private, rather than reducing compile
times, although it does both.

[...]
Fast execution times? Why is that?

The more the compiler knows, the better it can optimize. In
this case, however, I was thinking more along the lines of being
able to allocate the data directly on the stack, or in the
class, rather than needing a dynamic allocation.

If you want to see just how high the real cost can be, implement
a trivial Complex class (e.g. "double real, imag ;"---no need
for the operators for this test), then reimplement it using the
compilation firewall idiom (
class Complex
{
class Impl ;
Impl * myImp ;
public:
// ...
} ;
).
Now create an std::vector of a couple of million of each:).

Of course, this is an extreme example, but you get the idea.
My data structures won't change often, and I'm writing a performance
application, so I want speed where I can get it for free, for sure.

The question is what the difference is, and when. Using the
compilation firewall idiom requires an allocation in the
constructor, a delete in the destructor, and (generally) an
extra indirection in every function call. If the object
lifetimes are long, and the functions are complex, the
difference isn't measurable. If objects are frequently created
and destroyed (value semantics with deep copy, for example), and
the functions are almost trivial (complex::eek:perator+), the
difference can be important.
 
J

James Kanze

[...]
"Cheshire cat" ( 'handle class' ).

That was my favorite name for it too:). All you see is the
smile of the class. (Even though the technique goes back to
long before the name was invented.)
 
B

BobR

James Kanze wrote in message...
[...]
"Cheshire cat" ( 'handle class' ).

That was my favorite name for it too:). All you see is the
smile of the class. (Even though the technique goes back to
long before the name was invented.)

I should have mentioned my source. I modified Bruce Eckel's example for a
poster a couple years back. Bruce's footnote (for "Cheshire cat") in "TiCpp,
v1" says:

"[37] This name is attributed to John Carolan, one of the early pioneers in
C++, and of course, Lewis Carroll. This technique can also be seen as a form
of the "bridge" design pattern, described in Volume 2.
"

It's a handy little 'almost pattern' when someone wants to hide code from an
end user (like in a lib or *.so (<yech>DLL)).

I tried to use KISS (in what I posted) because member initialization(s)
depends on how/where control is needed.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top