473,378 Members | 1,512 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

pimpl, eliminating include files, encapsulation

(Note: this is a real C++ question and not an MS Windows question. The
window handle I introduce is just an example of OS specific data, which
I've used to illustrate my question.)

I have some code which is dependent on MS Windows. I want to encapsulate
this in a pimpl for all sorts of reasons, the main ones being:

1/ To encapsulate the OS dependent code

2/ To allow the header not to include the OS specific header files.
(In this particular case windows.h)
This allows the header to be OS independent and further
encapsulates the OS dependent code.

Unfortunately, the code needs a window handle (HWND). What's the best
way of passing this down without having to include windows.h in the
header? (HWND is defined in windows.h.)

Effectively I want to do something like this:

=== bloggs.cpp: low level OS dependent code ===

#include "bloggs.hpp"
#include "windows.h"

class bloggs::bloggsImpl
{
private:
HWND windowHandle_; // how does this get set?
public:
bloggsImpl(void){};
};

bloggs::bloggs():pimpl_(new bloggsImpl){}
bloggs::bloggs(const bloggs &C):pimpl_(new bloggsImpl)
{
*pimpl_ = *(C.pimpl_);
}

bloggs::~bloggs()
{
delete pimpl_;
}

bloggs& bloggs::operator=(const bloggs &C)
{
*pimpl_ = *(C.pimpl_);
return(*this);
}

=== bloggs.hpp: header for low level OS dependent code ===
class bloggs
{
public:
bloggs();
bloggs(const bloggs &C);
~bloggs();
bloggs& operator=(const bloggs &C);
private:
class bloggsImpl;
bloggsImpl* pimpl_;
};

=== smith.cpp: portable code ===
#include "bloggs.hpp"
#include "smith.hpp"
class smith::smithImpl
{
private:
bloggs privateBloggs_; // must somehow give this a window handle
public:
smithImpl(void){};
};

smith::smith():pimpl_(new smithImpl){}
smith::smith(const smith &C):pimpl_(new smithImpl)
{
*pimpl_ = *(C.pimpl_);
}

smith::~smith()
{
delete pimpl_;
}

smith& smith::operator=(const smith &C)
{
*pimpl_ = *(C.pimpl_);
return(*this);
}

=== smith.hpp: header for portable code ===
class smith
{
public:
smith();
smith(const smith &C);
~smith();
smith& operator=(const smith &C);
private:
class smithImpl;
smithImpl* pimpl_;
};

=== winbits.cpp: high level OS dependent code ===
#include "smith.hpp"
#include "windows.h"
....
HWND windowHandle;
....
smith* pSmith = new smith;
pSmith->CallOneOfSmithsMethods();
delete pSmith;

I would need to add a method to tell bloggs about the window handle. But
this would have to be passed through smith, which isn't allowed to know
about such things as window handles because it must be portable and OS
independent.

In this specific example I could cheat and pass the window handle as an
unsigned long, because I happen to know the type of HWND and I happen to
know that it isn't going to change anytime soon. But a) this seems like
a bit of a kludge and b) it's a very specific solution.

It's a pity that typedefs and enums can't be forward declared like
classes can. Otherwise I could pass a pointer to HWND.

Thoughts?
--
Simon Elliott
http://www.ctsn.co.uk/


Jul 22 '05 #1
6 1756
Simon Elliott wrote:
[redacted]

Insert the line "class bloggsImpl;" before your bloggs def.

=== bloggs.hpp: header for low level OS dependent code ===
class bloggsImpl; // NEW LINE. class bloggs
{
public:
bloggs();
bloggs(const bloggs &C);
~bloggs();
bloggs& operator=(const bloggs &C);
private:
class bloggsImpl;
bloggsImpl* pimpl_;
};


Jul 22 '05 #2
red floyd <no*****@here.dude> writes
Insert the line "class bloggsImpl;" before your bloggs def.

=== bloggs.hpp: header for low level OS dependent code ===


class bloggsImpl; // NEW LINE.
class bloggs
{
public:
bloggs();
bloggs(const bloggs &C);
~bloggs();
bloggs& operator=(const bloggs &C);
private:
class bloggsImpl;
bloggsImpl* pimpl_;
};


I don't understand how this allows me to solve the problem. Can you
expand a bit?
--
Simon Elliott
http://www.ctsn.co.uk/


Jul 22 '05 #3
"Simon Elliott" <si***@nospam.demon.co.uk> wrote in message
news:cy**************@courtlands.demon.co.uk
(Note: this is a real C++ question and not an MS Windows question. The
window handle I introduce is just an example of OS specific data,
which I've used to illustrate my question.)

I have some code which is dependent on MS Windows. I want to
encapsulate this in a pimpl for all sorts of reasons, the main ones
being:

1/ To encapsulate the OS dependent code

2/ To allow the header not to include the OS specific header files.
(In this particular case windows.h)
This allows the header to be OS independent and further
encapsulates the OS dependent code.

Unfortunately, the code needs a window handle (HWND). What's the best
way of passing this down without having to include windows.h in the
header? (HWND is defined in windows.h.)


Platform independent software development is not my specialty, but here is
my 2 cents worth.

I think you need to identify where the HWND value is coming from in the
first place. If, for example, the HWND is the return value from a
CreateWindow call, then you could provide a function that abstracts the
window creation process on all supported platforms and which, in the case of
Windows, uses the return value from CreateWindow to initialise the HWND
variable without the client code ever having to see it.
--
John Carson
1. To reply to email address, remove donald
2. Don't reply to email address (post here instead)

Jul 22 '05 #4
This is a lame atempt to write C++. Can you write a Hello World program? Do
you have a C++ book?
What I see here is duplicate declarations of classes (e.i. you declare twice
the "bloggs" class)
Can you shrink your example?

------------------------
snip snip snip snip snip
------------------------

Dan
Jul 22 '05 #5
Dan Cernat <ce****@dan.com> writes
What I see here is duplicate declarations of classes (e.i. you declare twice
the "bloggs" class)


Where?

--
Simon Elliott
http://www.ctsn.co.uk/


Jul 22 '05 #6
snip
...
smith* pSmith = new smith;
pSmith->CallOneOfSmithsMethods();
delete pSmith;

I would need to add a method to tell bloggs about the window handle. But this would have to be passed through smith, which isn't allowed to know about such things as window handles because it must be portable and OS independent.

In this specific example I could cheat and pass the window handle as an unsigned long, because I happen to know the type of HWND and I happen to know that it isn't going to change anytime soon. But a) this seems like a bit of a kludge and b) it's a very specific solution.

It's a pity that typedefs and enums can't be forward declared like
classes can. Otherwise I could pass a pointer to HWND.


Let's see... we need a void pointer but we don't want to be attacked
by anyone, so...

Your 'impl' classes will all want something different but need to be
called by the innocent unknowing wrapper so they will need a method
that takes a void pointer which they can static_cast appropriately.

Your wrapper classes will need to wrap the call so they will need an
equivalent method but since we don't want anyone doing anything that
isn't typesafe it must be private. And since we don't want anyone
using an improperly initialized wrapper, the constructor must be
private as well.

Moving to your sample implementation, the header file for 'smith' gets
a forward declaration for an OS dependent class called smithFactory
that will be it's friend. The header file for smithFactory will
include the header for smith.

smithFactory, being OS dependent, has a static method that takes a
pointer to whatever the corresponding 'impl' class expects (to allow
type checking), constructs a smith, makes the call that passes the
pointer along (could be a constructor argument) and returns a pointer
to the new object.

Any help?
Do I need help?
Tom
Jul 22 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: Icosahedron | last post by:
I've been going through some old code trying to clean it up and rearchitect it based on more modern C++ idioms. In the old code I often used the Pimpl idiom on a class by class basis, creating...
6
by: Asfand Yar Qazi | last post by:
Hi, Now that GCC 3.4 has precompiled headers, I'm thinking I can stop using pimpls to speed up development time, as it may make life easier (declaring pimpls takes a long time...) What are...
3
by: JackC | last post by:
Hi Problem: I wish to use a pimpl to hide implementation/storage of a class (T), but I also want to hold objects of that class (T) in an std::vector<T> (or similar). T is non trivial (i.e. not...
2
by: Peteris Krumins | last post by:
Hello! I was playing around pimpl idiom and discovered that there is a problem with it if a class member template function exists which has to access private data, since only the forward...
34
by: Asfand Yar Qazi | last post by:
Hi, I'm creating a library where several classes are intertwined rather tightly. I'm thinking of making them all use pimpls, so that these circular dependancies can be avoided easily, and I'm...
7
by: mliptak | last post by:
Hi group, suppose having this code using PIMPL: // a.hh class A { struct Impl; public: A();
17
by: Francine.Neary | last post by:
I have a program that uses a large lookup table, provided as a large array in the source: static int bigtbl={123, 456, /* etc. etc. */ 9999 }; Now this table is pretty big, and having it...
4
by: er | last post by:
hi, the code below generates the following behavior. cld someone please help understand it? 1) clean project + build project generates build errors (see bottom) 2) build a second time, errors...
2
by: Graham Reitz | last post by:
What are good strategies for selecting, either at run-time or compile time, various pimpl'ed implementations? While retaining the ability to switch implementations without recompiling. Boost...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.