3

我很好奇在 C++ 中这样做:

假设我有一个小型库,可以分发给我的用户。我为我的客户提供他们需要的二进制文件和相关的头文件。例如,假设在开发中使用了以下标头:

#include <string>

ClassA 
{
    public:
        bool setString(const std::string & str);

    private:
        std::string str;
};

现在我的问题。对于部署,我给我的客户一个“减少”的标题有什么根本错误吗?例如,我是否可以剥离私人部分并简单地给他们这个:

#include <string>

ClassA 
{
    public:
        bool setString(const std::string & str);
};

我的直觉说“是的,这是可能的,但是有问题”,这就是我在这里问这个问题的原因。如果这是可能的并且安全的话,它看起来是隐藏私有变量的好方法,因此在某些情况下甚至可以避免前向声明。

我知道这些符号仍然存在于二进制文件本身中,这只是源代码级别的可见性。

谢谢!

4

3 回答 3

6

以这种方式修改类声明会导致代码不兼容。

编译器需要类声明来确定该类的实例占用了多少空间以及成员变量在该空间中的位置。

如果您在一个标头中遗漏成员(甚至是私有成员),则使用此标头编译的代码将采用不同的类布局。它将为类的实例分配更少的空间,并假设成员变量位于不正确的位置。

于 2012-11-30T17:08:59.310 回答
2

Qt(一组跨平台 C++ 库)使用私有头文件和“d”指针隐藏实现细节的技术。我认为长时间维护具有二进制兼容性的库但能够在必要时更改实现是非常巧妙的。

http://zchydem.enume.net/2010/01/19/qt-howto-private-classes-and-d-pointers/

于 2012-11-30T17:26:28.407 回答
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();
}
于 2012-11-30T17:26:46.093 回答