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

时间:2015-05-14 18:23:42

标签: c++ static-libraries

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

出乎意料的是,在创建导出到静态库的类的实例时,我遇到了堆损坏错误。

这是我原来的头文件:

// 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 Operation会根据调用的位置返回不同的值。

在.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(来自链接库)有多大?或者是否有任何简单的方法可以隐藏用户不需要的头文件中的声明?

3 个答案:

答案 0 :(得分:2)

我不知道&#34;隐藏不重要的成员&#34;已连接到从类定义中删除它们。

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

问题是,你完全改变了你的课程。如果它被设计为有三个私人成员:

SQLHENV     m_henv;
SQLHDBC     m_hdbc;
SQLHSTMT    m_hstmt;

你不能只是删除它们。这不是&#34;隐藏实现细节&#34;装置

  

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

您想要的是使用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。

答案 1 :(得分:1)

您可以公开接口而不是类+工厂类。这样,您的用户就无法看到实际课程的结构,一切正常。

例如,您的用户可以获得此信息:

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

答案 2 :(得分:0)

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