我最近决定将我的一些函数导出到静态库(.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 Header文件:

// 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 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而不是分别使用每个组件。如果要更新您的软件,这特别有利可图-它禁止客户端创建代码,这取决于您类型的实现细节。

您可能还想阅读this answer的第2点和/或4.点。

关于c++ - 我们可以在头文件中隐藏不重要的声明吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30244594/

10-11 22:57
查看更多