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

Can we hide unimportant declarations in Header files?

本文关键字:重要的 不重要 声明 隐藏 文件 我们      更新时间:2023-10-16

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

在创建导出到静态库的类的实例时,意外地遇到堆损坏错误。

这是我原来的头文件:

// 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头文件:

// Minimized Header File
class CODBCHelper
{
public:
    CODBCHelper();
    virtual ~CODBCHelper();
public:
    std::vector<UserData> getUserInformation();
};

我注意到sizeof操作返回不同的值取决于它被调用的位置。

在.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];
}

可以解决这个问题,但我认为这是很糟糕的行为,而且根本不可维护。

所以有没有办法告诉编译器有多大的真正的对象(从链接库)将是?或者在头文件中隐藏用户不需要的声明是否有简单的方法?

我不明白"隐藏不重要的成员"是如何与从类定义中删除它们联系在一起的。

我猜,你想从你的代码中消除不必要的依赖。这是一种很好的技术——它减少了编译时间,使代码在不同版本之间更易于移植,等等。

问题是,你完全改变了你的类。如果它被设计为有三个私有成员:
SQLHENV     m_henv;
SQLHDBC     m_hdbc;
SQLHSTMT    m_hstmt;

你不能直接删除它们。这不是"隐藏实现细节"的意思。

或者在头文件中隐藏用户不需要的声明是否有简单的方法?

您需要的是使用PIMPL习惯用法:

//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。和/或

可以公开接口,而不是类+工厂类。这样你的用户就看不到你实际类的构造,一切都很好。

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

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

创建一个具有纯虚方法的public抽象类,不包含数据。然后创建一个工厂/访问器来实例化/访问库代码中的实际对象,该对象实际上是抽象类的派生/具体类。