我昨天问了另一个与此类似的问题,但我想我在试图解释自己时遇到了 XY 问题,所以让我们再试一次。
我真的不喜欢这样的想法:投入大量精力仔细开发和设计 C++ 库,只是为了阻止那些链接 DLL 的人访问他们不应该访问的数据,即使是意外是 DLL 附带的
.h
文件中提供的手写访问修饰符。
在编译 DLL 后,我可以考虑什么解决方案来重新创建访问修饰符的概念,而这些解决方案不能像在与分发版本一起打包的
.h
文件中重写访问修饰符那样简单地进行更改DLL?
我考虑过但不完全理解的解决方案是仅在
__declspec(dllexport)
API 方法、public
等上指定 class
,以便将 .h
文件中的某些项目重写为 public
当它应该是 private
时并不重要,因为 LIB 文件不会填充该项目,因此链接 DLL 的人无法使用它。我并不像我说的那样完全理解这个解决方案,因此不能自信地说这是否是我问题的答案(似乎只是 .def
文件的简单版本,这是昨天向我解释的文件)但我只是想提高我对它的认识,如果你认为它有用,请在我投入到用它来膨胀现有库之前让我知道,结果却发现它根本不起作用(我想我应该只设置一个 MRE,但现在我只是在胡言乱语)。
非常感谢您的阅读!
正如您和其他人在评论中提到的,PIMPL 模式背后的主要动机之一正是为了解决您所描述的问题。
简化的实现可能如下所示:
// 'Foo.h'
// Forward declare FooImpl here, but no definition in public header !
// What is or does is not accessible to the user of this header.
class FooImpl;
class Foo
{
public:
Foo();
~Foo();
// bar() works some magic that we don't want to leak to the outside.
int bar();
private:
FooImpl* pImpl;
};
// 'Foo.cpp'
#include Foo.h
// Define FooImpl here or in a separate and private (not distributed) header,
// so that it won't be visible to consumers of this lib.
class FooImpl
{
public:
void FooImpl(){};
int bar()
{
return someMagic;
};
private:
int someMagic{42};
};
void Foo::Foo()
{
pImpl = new FooImpl{};
}
void Foo::~Foo()
{
delete pImpl;
}
int Foo::bar()
{
return pImpl->bar();
}
本质上,只有类的外部接口
Foo
在其标头中保持可见,即消费者实际使用该类所需的函数和定义。
所有实现细节(包括私有函数和成员变量)都隐藏在第二层下,即 FooImpl
类。
请注意,虽然这将为您的库的用户隐藏实现细节,但它当然不是任何意义上的针对反编译或其他此类黑客工具的安全措施。