what are the rules for writing header files?

D

Daniel T.

Hello all,

I have written a class with many private data members.and i am putting
it in a separate dll file.
Now when i link that file while writing my main program
module,natuarally i have to use the header file of the class developed
by me to access its functionality.
so what should be there in the header file?
Only the public methods declaration / data members of that class or the
whole layout of the class along with its all private members?
(
IMO the private section restricts the accessibility of the class and
the user of the class is abstracted from the exact layout of the
class.So there should be no need to show the internal layout of my
class by putting the private variable inside the header file of that
class.
)

I encountered severe crasing problem when I declare the class without
the private members in the header file? but everything works fine when
i put the exact layout of the class correctly inside the header file.
(i have defined all the public methods inside a separate cpp file with
the scope resolution operator)

You have some very valid concerns. As you have learned, you can't change
the header file without recompiling all the object files that include
it. By putting the data in the header file, even in the private part of
a class, all of the object files (the DLL and *all* programs that depend
on that DLL) will have to be recompiled every time you make any change
in the data.

Edson Manoel gave you the best advice by far. Use the pimpl idiom to
solve this problem:

// file y.h
class X;

class Y {
// remove all the private parts
X* px_;
public:
Y();
Y( const Y& other );
~Y();
Y& operator=( const Y& other );
// ...
};

// file y.cpp
class X {
// everything that was private in Y
};

Y::Y() : px_( new X ) {}
Y::Y( const Y& other ) {
*px_ = other.px_;
}
Y::~Y() { delete px_; }
Y& operator=( const Y& other ) {
*px_ = other.px_;
}


By doing the above, you will be able to add/remove private bits without
having to recompile users of the Y class.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
C

Carl Barron

Daniel T. said:
Edson Manoel gave you the best advice by far. Use the pimpl idiom to
solve this problem:

// file y.h
class X;

class Y {
// remove all the private parts
X* px_;
public:
Y();
Y( const Y& other );
~Y();
Y& operator=( const Y& other );
// ...
};

// file y.cpp
class X {
// everything that was private in Y
};

Y::Y() : px_( new X ) {}
Y::Y( const Y& other ) {
*px_ = other.px_;
}
Y::~Y() { delete px_; }
Y& operator=( const Y& other ) {
*px_ = other.px_;
}
This produces a shallow copy that is:
Y a;
Y b(a);
a and b have the same values of private data and if when they are
destructed one of the destructors will delete a deleted pointer. Ouch!!
its not quite so simple. You must deep copy the pointers , create a
pointer to a copy of the class X, not just a copy of the X *.

Y:Y() {p_x = new X;}
Y:Y(const Y &r) {p_x = new X(*r.p_x);}
Y & operator () (const Y &r)
{
X *p = new X(*r.p_x); // in case of self assign.
delete p_x;
p_x = p;
return *this;
}
Y:~Y() {delete p_x;}

comes to mind. These ctor's will throw if there is insufficient memory,
but otherwise make Y Copyable and Assignable.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
D

Daniel T.

Carl Barron said:
This produces a shallow copy that is:
Y a;
Y b(a);
a and b have the same values of private data and if when they are
destructed one of the destructors will delete a deleted pointer. Ouch!!
its not quite so simple. You must deep copy the pointers , create a
pointer to a copy of the class X, not just a copy of the X *.

Y:Y() {p_x = new X;}
Y:Y(const Y &r) {p_x = new X(*r.p_x);}
Y & operator () (const Y &r)
{
X *p = new X(*r.p_x); // in case of self assign.
delete p_x;
p_x = p;
return *this;
}
Y:~Y() {delete p_x;}

comes to mind. These ctor's will throw if there is insufficient memory,
but otherwise make Y Copyable and Assignable.

Sorry, I was a little short with my code, for example my copy c_tor, and
op= wouldn't compile as they stand...

Y::Y() : px_( new X ) { }
Y::Y( const Y& o ): px_( new X( *o.px_ ) ) { }

The above is a bit better than your c_tors
<http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6> In my
original copy c_tor, I forgot to create a new X then tried to
dereference it which is bad.

The big difference between our code is the op=, I see nothing wrong
with mine (other than the missing dereference.)

Y& operator=( const Y& o ) {
*px_ = *o.px_;
}

All the hoops you jump through in your op= are wholly unnecessary,
unless class X doesn't have an op=. (And if it has a copy c_tor, it darn
well should have an op= as well.)

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
C

Carl Barron

Daniel T. said:
The big difference between our code is the op=, I see nothing wrong
with mine (other than the missing dereference.)

Y& operator=( const Y& o ) {
*px_ = *o.px_;
}

All the hoops you jump through in your op= are wholly unnecessary,
unless class X doesn't have an op=. (And if it has a copy c_tor, it darn
well should have an op= as well.)
If X has an assignment operator then yours is faster. I wrote it
off the cuff and did not want to create another double delete error.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 

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

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,219
Latest member
KristieKoh

Latest Threads

Top