1

Okay, I have a class called a Window which is designed to take care of all of the requirements of putting together a window and it works wonderfully. My only issue is that any file that I include window.h in also gets all of the windows includes as well. I've made all of the windows-specific elements private, so there's no real reason that the rest of my project needs to know about those elements and I'd rather know beyond a shadow-of-a-doubt that I've not accidentally made other bits and pieces windows-specific on accident.

The only way that I've been able to figure out to do this would be to create a second class that contains these elements and place a pointer to an instance within the first class. For an example of what I'm talking about, lets start off with the following file "ElementsIWantHidden.h"

#ifndef ELEMENTS_I_WANT_HIDDEN_H
#define ELEMENTS_I_WANT_HIDDEN_H

typedef short int16;
typedef int int32;
typedef long long int64;

#endif

Lets assume that these are some defines that come with some other functions, similar to how windows.h defines WHND. I need the windows functions and I need my window class to use them, but I don't want to make the mistake of accidentally using some of these defines outside of my windows class.

If I have the file "TraditionalClass.h" with the following code:

#ifndef TRADITIONAL_CLASS_H
#define TRADITIONAL_CLASS_H

#include "ElementsIWantHidden.h"

class TraditionalClass
{
private:
    int16 shortInt;
    int32 mediumInt;
    int64 longInt;
public:
    TraditionalClass();
    void print();
};

#endif

then any file that includes TraditionalClass.h also includes windows.h, has to compile windows.h, and has all of the windows functions and types available to it.

The only workaround I've been able to figure out is to have something like the file "ClassWithHiddenElements.h" with the code:

#ifndef CLASS_WITH_HIDDEN_ELEMENTS
#define CLASS_WITH_HIDDEN_ELEMENTS

class HiddenElementsContainer;

class ClassWithHiddenElements
{
private:
    HiddenElementsContainer* hiddenElementsContainer;
public:
    ClassWithHiddenElements();
    ~ClassWithHiddenElements();
    void print();
};

#endif

ClassWithHiddenElements.cpp then defines or includes a file defining HiddenElementsContainer and in the constructor creates and instances and in the destructor deletes it.

This works and classes that include ClassWithHiddenElements.h can't see anything defined within ElementsIWantHidden.h. The problem is that members of ClassWithHiddenElements that use those types must be hidden behind a pointer which slows down accessing. ClassWithHiddenElements must now have a copy constructor, copy operator, and destructor. There is the potential to run out of memory part way through constructing ClassWithHiddenElements when more memory gets allocated to create the instance of ElementsIWantHidden which means the constructor can't have a no-throw guarentee. Some of these aren't big issues, as there're a lot of other things which will often create these. Is there a better way to accomplish this goal though? I need to include instance variables of types from windows.h, but I don't want it to pollute the rest of the project.

FYI, this is for game development and I want the final product to be cross-platform compatible, which is a large part of the reason that I don't want elements of windows.h to get accidentally used in other files that aren't supposed to be OS aware.

Darinth
  • 511
  • 3
  • 14
  • 4
    I think you're looking for the [pimpl idiom](http://herbsutter.com/gotw/_100/) – Praetorian Jan 26 '14 at 06:43
  • That's pretty much exactly what I'm doing. Good to see that this is a known pattern for hiding implementation details. My only concern then is how much a difference there is in overhead for calling functions, retrieving variables, etc... from the pimpl and if there are any other methods of accomplishing this. – Darinth Jan 26 '14 at 08:49

1 Answers1

1

Make the typedefs part of your class:

class TraditionalClass
{
private: // can make them public also
    typedef short int16;
    typedef int int32;
    typedef long long int64;

private:
    int16 shortInt;
    int32 mediumInt;
    int64 longInt;
public:
    TraditionalClass();
    void print();
};

This way inside the class you can refer to your types simply without any qualification name.

From outside the class, you can't access them at all if they are private. If they are public you can access them with their qualified name only: TraditionalClass::int16.

Another way is to create a namespace and put both the class and the typedefs in that namespace. Regardless of where you put the typedefs, you should create a namespace for your class.

bolov
  • 72,283
  • 15
  • 145
  • 224
  • I tried to do something like this, with namespace Windows { #include } but a lot of the windows related content didn't get placed in the namespace and I wasn't ever able to get it to compile. As an example LRESULT wasn't placed in the namespace, but wasn't usable outside of it either. I was getting errors no matter where I tried to use it. – Darinth Jan 26 '14 at 08:26