我可以使用我的标题的精简版本包含在库中吗?

Ada*_*ran 6 c++ oop

我的意思是我真正的头文件看起来像这样:

#include "some_internal_class.h"

class MyLibrary {
    Type private_member;

    void private_function();
public:

    MyLibrary();
    void function_to_be_called_by_library_users();
};
Run Code Online (Sandbox Code Playgroud)

现在我想生成一个包含所有必要定义的动态库.我想用它来发送一个标题,而不是发送我库中的每一个标题.

所以我想我可以像这样创建一个瘦小版本的标题:

class MyLibrary {
public:     
    MyLibrary();
    void function_to_be_called_by_library_users();
};
Run Code Online (Sandbox Code Playgroud)

标题只是声明无论如何正确吗?它们永远不会传递给编译器.我已经宣布了用户将使用的内容.

那可能吗?如果没有,为什么不呢?

Sto*_*ica 7

这是一个定义规则违规.你偏离一个令牌的那一刻.

[basic.def.odr]/6

在程序中可以有多个类类型的定义,[...]只要每个定义出现在不同的翻译单元中,并且定义满足以下要求即可.鉴于这样一个名为D的实体在多个翻译单元中定义,那么

  • D的每个定义应由相同的令牌序列组成; 和

如果您违反ODR,您的程序可能会轻易破坏.而你的构建系统根本没有义务甚至警告你.


lis*_*rus 2

无论如何,标题只是声明,对吗?它们永远不会传递给编译器。我已经声明了用户将使用什么。

不会。标头是源代码的一部分,与源文件一起编译。它们包含编译器理解如何使用代码(在您的情况下,使用 class MyLibrary)所需的信息。

例如,您希望库用户能够创建 class 的对象MyLibrary,因此您导出构造函数。然而,这还不够:编译器需要知道要创建的对象的大小,除非指定所有字段,否则这是不可能的。

在实践中,决定向库用户公开什么以及隐藏什么作为实现细节是一个难题,这需要对库的使用和语义进行详细检查。如果您确实想隐藏类内部作为实现细节,这里有一些常见的选项:

  • pimpl惯用法是一种常见的解决方案它使您能够像通常那样使用该类,但实现细节被很好地隐藏了。
  • 将接口提取为具有虚函数的抽象类,并使用指针(最好是智能指针)来操作对象。