我们可以在 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 .
我最近决定将我的一些函数导出到静态库 (.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