我们可以在 Header 文件中隐藏不重要的声明吗?

Can we hide unimportant declarations in Header files?

我最近决定将我的一些函数导出到静态库 (.lib)。我还决定不向用户提供完整的 header 文件。我保留了私有和受保护的变量和方法,因为 end-users 不应该使用它们,也不应该为 Class 声明包含其他 headers。

在创建导出到静态库的 Classes 实例时,我 运行 出乎意料地遇到了 heap-corruption 错误。

这是我的原始 header 文件:

// Original Header File
class CODBCHelper
{
public:
    CODBCHelper();
    virtual ~CODBCHelper();

public:
    std::vector<UserData> getUserInformation();

private:
    SQLHENV     m_henv;
    SQLHDBC     m_hdbc;
    SQLHSTMT    m_hstmt;
};

然后我决定去掉私有变量,这样我的 .lib 用户就不会滥用它们,也不必包含不必要的 SQL Header 文件:

// Minimized Header File
class CODBCHelper
{
public:
    CODBCHelper();
    virtual ~CODBCHelper();

public:
    std::vector<UserData> getUserInformation();
};

我注意到 sizeof 操作 returns 不同的值取决于它被调用的地方。

在 .lib 中调用:

int size = sizeof(CODBCHelper);
// size is 12

在链接项目中调用:

int size = sizeof(CODBCHelper);
// size is 1

在我的链接项目中执行以下代码会导致堆损坏(这可能是因为大小计算错误):

CODBCHelper* helper = new CODBCHelper;

做类似

的事情
class CODBCHelper
{
[...]
private:
    char padding[12];
}

会解决问题,但我认为它的行为非常糟糕,根本无法维护。

那么有什么方法可以告诉编译器真正的 Object(来自链接库)有多大?或者有什么简单的方法可以隐藏用户不需要的 header 文件中的声明?

使用纯虚拟方法创建抽象 class,即 public,无数据。然后创建一个 factory/accessor 到 instantiate/access 你的库代码中的实际对象实际上是抽象 class.

的 derived/concrete class

您可以公开接口而不是 classes + 工厂 class。这样您的用户就看不到您实际 classes 的构造,并且一切正常。

例如,您的用户得到这个:

class ICODBCHelper
{
public:
    virtual ~ICODBCHelper();

public:
    virtual std::vector<UserData> getUserInformation();
};

class MyFactory
{
public:
    ICODBHelper *CreateCODBHelper();
}

然后你实现这个:

class CODBCHelper : public ICODBHelper
{
public:
    CODBCHelper();
    virtual ~CODBCHelper();

public:
    std::vector<UserData> getUserInformation();

private:
   SQLHENV     m_henv;
   SQLHDBC     m_hdbc;
   SQLHSTMT    m_hstmt;
};

我不明白 "hiding unimportant members" 与从 class 定义中删除它们有什么关系。

我猜,您想从代码中消除不必要的依赖项。这是一项很好的技术 - 它减少了编译时间,使您的代码在不同版本之间更具可移植性等等。

问题是,您 完全 class 改变了 。如果它被设计为具有三个私有成员:

SQLHENV     m_henv;
SQLHDBC     m_hdbc;
SQLHSTMT    m_hstmt;

你不能只删除它们。这不是"hiding implementation details"的意思。

Or is there any easy way of hiding declarations in header files that are not needed by users?

你想要的是使用PIMPL Idiom:

//Minimized header file
class CODBCHelper
{
public:
    CODBCHelper();
    virtual ~CODBCHelper();

public:
    std::vector<UserData> getUserInformation();

private:
    struct InternalData;
    InternalData* m_internal_data;
};

然后,在您的 .cpp 文件中:

struct CODBCHelper::InternalData
{
    SQLHENV     m_henv;
    SQLHDBC     m_hdbc;
    SQLHSTMT    m_hstmt;
};

现在您将实现更改为使用 m_internal_data 而不是单独使用每个组件。如果您的软件将被更新,这将特别有利可图 - 它禁止客户创建代码,这取决于您的类型的实现细节。

您可能还想阅读 2. and/or 4. of .