我很好奇在C ++中这样做:
假设我有一个小型图书馆,我分发给我的用户。我给我的客户端他们需要的二进制文件和相关的头文件。例如,假设在开发中使用以下标头:
#include <string>
ClassA
{
public:
bool setString(const std::string & str);
private:
std::string str;
};
现在提出我的问题。对于部署,我有什么根本性的错误来减少&#39;标题给我的客户?例如,我可以剥离私人部分并简单地给他们这个:
#include <string>
ClassA
{
public:
bool setString(const std::string & str);
};
我的直觉说'是的,这是可能的,但有些问题&#34;,所以这就是为什么我在这里问这个问题。如果这是可能的并且也是安全的,那么它看起来是隐藏私有变量的好方法,因此在某些情况下甚至可以避免前向声明。
我知道这些符号仍然存在于二进制文件中,并且这只是源代码级别的可见性。
谢谢!
答案 0 :(得分:6)
以这种方式修改类声明将导致代码不兼容。
编译器需要类声明来确定该类的实例占用多少空间以及该空间中成员变量所在的位置。
如果在一个标题中省略成员(甚至是私有成员),使用此标题编译的代码将采用该类的不同布局。它将为类的实例分配更少的空间,并假设成员变量位于不正确的位置。
答案 1 :(得分:2)
Qt(一组跨平台C ++库)使用一种使用私有头和“d”指针隐藏实现细节的技术。我认为很长一段时间维护具有二进制兼容性的库是非常灵活的,但是必要时可以更改实现。
http://zchydem.enume.net/2010/01/19/qt-howto-private-classes-and-d-pointers/
答案 2 :(得分:2)
除了他在回答中所说的,我还要补充一点,如果你有理由做这样的事情,那么为什么不简单地让ClassA成为一个“接口”类型的类,它只有纯虚函数。
然后,您的内部代码将具有从ClassA派生的ClassB,并实现所有这些纯虚函数。您只为ClassA 分发标题。显然用户不能在堆栈上声明ClassA对象,因为ClassA是纯虚拟类,并且不能直接在堆栈或堆上创建ClassB对象,因为他对ClassB一无所知。
公共标题文件(将其分发给用户):
class A
{
public:
virtual ~A()
{ // necessary - don't remove.
}
virtual somefunc() = 0;
virtual someotherfunc(int a, int b) = 0;
virtual bool setString(const std::string & str) = 0;
};
// This function creates an instance of object B. You must
// call delete on the returned pointer when you're done with it!
A *CreateObjectB();
私人标题文件:
class B : public class A
{
private:
...
public:
B();
virtual ~B();
virtual somefunc();
virtual someotherfunc(int a, int b);
virtual bool setString(const std::string & str);
};
私人来源档案:
classB::B()
{
}
classB::~B()
{
}
classB::somefunc()
{
...
}
classB::someotherfunc(int a, int b)
{
...
}
classB::setString(const std::string & str)
{
...
}
A *CreateObjectB()
{
return new B();
}