避免头文件“污染”

时间:2014-01-26 06:39:55

标签: c++ class cross-platform

好的,我有一个名为Window的类,它旨在满足组合窗口的所有要求,并且它工作得非常好。我唯一的问题是,我包含window.h的任何文件也会包含所有窗口。我已经将所有特定于窗口的元素都设置为私有,所以没有任何理由让我的项目的其余部分需要知道这些元素,而且我宁愿知道我还没有怀疑的影子。意外地在事故中特意制作了其他点点滴滴。

我能够想出这样做的唯一方法是创建一个包含这些元素的第二个类,并在第一个类中放置一个指向实例的指针。举一个我正在谈论的例子,让我们开始使用以下文件“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

让我们假设这些是一些其他函数附带的定义,类似于windows.h定义WHND的方式。我需要windows函数,我需要我的窗口类来使用它们,但是我不想错误地在我的windows类之外使用这些定义中的一些。

如果我的文件“TraditionalClass.h”包含以下代码:

#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

然后任何包含TraditionalClass.h的文件都包含windows.h,必须编译windows.h,并且具有所有可用的windows函数和类型。

我能够弄清楚的唯一解决方法是使用代码文件“ClassWithHiddenElements.h”:

#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然后定义或包含一个定义HiddenElementsContainer的文件,并在构造函数中创建和实例,并在析构函数中删除它。

这项工作和包含ClassWithHiddenElements.h的类无法在ElementsIWantHidden.h中看到任何定义。问题是使用这些类型的ClassWithHiddenElements成员必须隐藏在指针之后,这会降低访问速度。 ClassWithHiddenElements现在必须具有复制构造函数,复制运算符和析构函数。当分配更多内存来创建ElementsIWantHidden实例时,有可能通过构造ClassWithHiddenElements而部分耗尽内存,这意味着构造函数不能拥有无抛出保证。其中一些不是大问题,因为还有很多其他事情会经常造成这些问题。有没有更好的方法来实现这个目标呢?我需要在windows.h中包含类型的实例变量,但我不希望它污染项目的其余部分。

仅供参考,这是用于游戏开发的,我希望最终产品能够跨平台兼容,这是我不希望在其他文件中偶然使用windows.h元素的一大部分原因。不应该是操作系统意识。

1 个答案:

答案 0 :(得分:1)

制作班级的typedefs部分:

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();
};

通过这种方式,你可以在没有任何资格名称的情况下引用你的类型。

从课堂外部,如果private,则根本无法访问它们。如果它们是public,您只能使用其限定名称访问它们:TraditionalClass::int16

另一种方法是创建一个名称空间,并将该类和typedefs放在该名称空间中。无论你把typedef放在哪里,你都应该为你的类创建一个命名空间。