静态库:从头文件中隐藏私有成员
Posted
技术标签:
【中文标题】静态库:从头文件中隐藏私有成员【英文标题】:Static library: hiding private members from header file 【发布时间】:2014-05-01 20:43:01 【问题描述】:我希望将我的部分代码编译为静态库以包含在其他项目中。当然,我必须分发已编译的库和包含类声明和公共成员的头文件,但我不知道是否可以将所有私有成员和声明移动到与头文件不同的位置。
例子:
在project.h文件中:
class MyClass
public:
MyClass();
void Give_me_an_input(int);
int Get_your_output();
private:
int a, b;
int MySecretAlgorithm();
;
.cpp 文件中:
MyClass::MyClass()
a = 1;
b = 0;
void MyClass::Give_me_an_input(int c)
b = c;
int MyClass::Get_your_output()
return MySecretAlgorithm();
int MyClass::MySecretAlgorithm()
return (a + b);
有没有办法将所有私有成员int a, b;
和int MySecretAlgorithm();
移动到与头文件不同的位置?
【问题讨论】:
否,因为它们是类定义所必需的。但是您可以使用例如重新实现该类pimpl idiom(以某种间接为代价。) 你是否关心其他人是否只能看到声明?您可以使用一些无意义的虚拟名称来声明它。然后,在cpp
文件中,实现它。在您的秘密文件中,创建一个指向此函数的指针,并使用有意义的名称
如果你想对使用这个库的人隐藏信息,你可以考虑使用vector<void*>
之类的东西,并根据需要转换元素。不过,它不会很漂亮。
+1 表示 pimpl 成语
您为什么要这样做?动机/目标是什么?
【参考方案1】:
在这种场景下可以使用指向实现习语的指针,通常称为pimpl。 基本思想是将实现细节从声明中取出 并且只是有一个指向实现细节的不透明指针。
std::unique_ptr
用于以下示例;但你当然可以只使用普通指针。
// my_class declaration unit.
class my_class
private:
class impl;
unique_ptr<impl> pimpl;
public:
;
// my_class implementation unit
class my_class::impl
int whatever;
int whenever;
;
my_class::my_class(): pimpl( new impl )
【讨论】:
呃 - 我忘了这样做 - 这确实是最好的方法。 但是,对于静态链接库,隐藏实现细节根本没有意义,因为没有 ABI 问题,因此几乎没有任何收获。【参考方案2】:多年来,我看到了一些黑客来做到这一点,但我认为它们不值得。如果您的库相当“笨重”(即:没有方法被调用十亿次每微秒);你可以重写你的代码块......
您可能会考虑将所有公共内容设为抽象类(所有虚拟 = 0),然后从中派生具体类。
这方面的缺点: - 你所有的公共电话都变成虚拟的(一些优化可以绕过这个,但不经常)。 - 你不能再“新建”你的类了,你需要实现一个工厂模式。
我熟悉的任何其他 hack 的问题是,它们基本上在一组标头中声明方法,然后在私有标头中使用“真实”实现重新声明相同的东西 - 取决于链接器匹配名称。这里有几个问题:
维护这个烂摊子很糟糕。您不能使用#ifdef,因为听起来您想要物理隐藏您的实现。因此,您有双重维护,或生成公共标头的构建步骤。
只能通过指针使用。您必须将构造函数设为私有并且仍然拥有工厂,因为如果您让客户端按值(甚至使用 new)生成结构体,编译器将不会生成正确大小的结构体。
最后,我曾经看到一个 hack,程序员试图在“公共”类的私有区域中声明一个字节数组,以便客户端代码仍然可以按值声明或自己“新建”它。这会遇到所有以前的问题,而且您可能不想“知道”结构的大小,因为它们依赖于打包和对齐。您的“构建步骤”或多或少必须有一个使用 sizeof() 的运行时组件 - 现在如果您想更改结构/类的大小,则会遇到版本控制问题。
【讨论】:
以上是关于静态库:从头文件中隐藏私有成员的主要内容,如果未能解决你的问题,请参考以下文章