类或函数声明中的宏

时间:2015-12-04 16:09:50

标签: c++ class macros

我已阅读相关问题,如thisthis以及其他页面,但它们并未真正回答我的问题。

基本上,我看到如下代码。

class SOME_MACRO SomeClass{
    SomeClass();
    ~SomeClass();
};

这对我来说真的很困惑。现在我认为自己对C ++有了相当的了解(尽管对预处理器来说不那么熟悉),但我不记得在我读过的任何一本书中看过这样的声明。但是我总是在现实世界中看到这样的代码,例如在OpenCV中。你在书中或课堂上学到的C ++和你在实践中实际看到的C ++之间似乎存在差异,我觉得这很不幸。

我从herehere学到了如上所述的宏用于告诉链接器如何正确链接它,或类似的东西。对于the example hereQuickFAST_Export变为__declspec(dllexport)__declspec(dllimport)。在其他情况下,这些宏告诉链接器如何运行,具体取决于系统是Linux还是Windows。我从抽象的角度了解这一切;我知道那里有什么宏,我知道他们现在做了什么,至少大致如此。所以我不希望像“那些宏在那里你可以改变[...]”这样的答案,因为那些答案并没有告诉我如何在我自己的程序中使用这种声明我可能会从头开始写作。

我的问题是,从什么时候将__declspec(dllimport)这样的东西放在类声明的中间是合法的呢?实际的是__declspec(dllimport)int?一个东西?在C ++标准的哪个部分,它说这样的类声明是合法的?如果有人可以编写一个最小程序来说明一个类声明,在它的中间有一个非平凡(非空)的宏,那就编译并最好做一些可见的东西,我将非常感激。

4 个答案:

答案 0 :(得分:5)

  

我从这里和这里学到了如上所述的宏用于告诉链接器如何正确链接它或类似的东西。

要迂腐,不会告诉链接器如何链接。宏被预处理器简单地替换为它被定义为替换的任何文本。对于您的示例,它会被__declspec(dllexport)__declspec(dllimport)有条件地替换。另一方面,那些declspec说明符确实告诉链接器要做什么...至少一些了解说明符的链接器。

  

因为什么时候把__declspec(dllimport)这样的东西放在类声明的中间是合法的呢?

由于Microsoft实施了他们的编译器并指明它是合法的。根据c ++标准,这是不合法的。

  

在C ++标准的哪个部分中它表示像这样的类声明是合法的?

它没有。使用这些说明符是非标准的,并不保证可以在除Microsoft以外的任何其他编译器中使用。这就是为什么在不支持关键字的编译器中使用这种宏时,通常将其定义为扩展为空字符串(或者可能是其他实现的其他内容)。

  

__declspec(dllimport)实际上是什么东西?

这是一个非标准的关键字。您可以从他们的(Microsoft)documentation中找到更多信息。

为了进一步深入,关键字告诉链接器在编译共享(动态链接)库时如何导出符号。动态链接是一个完全不符合标准的概念。它的实现已定义。

  

我自己可以在一个程序中使用这种声明,我可以自己从头开始编写。

您打算写一个共享库吗?如果没有,那么你不需要知道。如果是,那么您需要阅读您正在瞄准的每个平台的文档。

以下是Microsoft文档中的walkthrough,它指导您完成创建动态链接库的步骤。

答案 1 :(得分:2)

规范未指定如何将程序链接到一起或链接到外部库,或构建库,或者坦白地说任何与链接器有关的事情,而不是在翻译单元中可见的符号。

即使通过语言扩展,实现也可以自由地负责实现他们想要的所有内容。任何带有两个下划线的东西都是实现分配的。所以关于那里发生的事情的一切都是合法的,你不会在规范的任何地方找到它。

答案 2 :(得分:2)

对于下划线附近的标识符(例如__attribute____declspec)和前导下划线后跟大写字符(例如_Bool_Thread_local)(通常)保留供编译器将来使用和使用。这意味着正常的语言规则不适用于您的示例,因为编译器可以自由扩展语言。 (C.f.“What are the rules about using an underscore in a C++ identifier?”)

查看GCC的大量语言扩展列表:https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html#C-Extensions

输入实际上只在预处理之后解析SOME_MACRO也可以包含X; class所有的好处。

答案 3 :(得分:1)

__declspec(dllimport)

您可以根据您正在执行的操作,使用的编译器,您要定位的操作系统,ext来设置多种类型的属性和说明符。大多数人学到的不是针对特定的编译器,而是每个人都支持的核心C ++ / C标准。