代码之家  ›  专栏  ›  技术社区  ›  EFraim

C中的内联成员函数++

  •  15
  • EFraim  · 技术社区  · 16 年前

    ISO C++表示,C++中成员函数的内联定义与内联声明相同。这意味着该函数将在使用成员函数的每个编译单元中定义。但是,如果函数调用因任何原因无法内联,则该函数将“照常”实例化。 ( http://msdn.microsoft.com/en-us/library/z8y1yy88%28VS.71%29.aspx )我对这个定义的问题是,它没有说明它将在哪个翻译单元中实例化。

    在静态库中

    A.h:
    
    class A{
      public:
        virtual bool foo() { return true; }
    };
    

    A a1;
    

    U2.cpp:

    A a2;
    

    以及大量的依赖关系

    main.cpp:

    #include "A.h"
    
    int main(){
      A a;
      a.foo();
      return 0;
    }
    

    第二个项目是指第一个项目。我如何知道编译器将使用哪个定义,从而知道哪些对象文件及其依赖关系将被链接?标准对这件事有什么规定吗?(试过了,但没找到)

    谢谢

    编辑:由于我看到一些人误解了问题是什么,我想强调一下: 如果编译器决定为该函数创建一个符号(在这种情况下,由于“虚拟性”,它将在不同的对象文件中有几个(外部可见的)实例化,链接器将选择哪个定义(来自哪个对象文件?)?)

    5 回复  |  直到 16 年前
        1
  •  8
  •   Johannes Schaub - litb    16 年前

    只有我的两分钱。这不是特别关于虚函数,而是关于内联函数和成员函数。也许它是有用的。

    就标准C++而言,内联函数 必须 在使用它的每个翻译单元中定义。非静态内联函数在每个转换单元中都有相同的静态变量和相同的地址。编译器/链接器必须将多个定义合并到一个函数中才能实现这一点。因此,始终将内联函数的定义放在头中——或者如果你只在实现文件(“.cpp”)中定义了它(对于非成员函数),则不在头中声明它,因为如果你这样做,并且有人使用了它,你会得到一个关于未定义函数或类似东西的链接器错误。

    ).对于内联函数,如上所述的多个定义是很正常的情况。这与调用是否自然内联无关。关于内联函数的规则仍然很重要。微软编译器是否遵守这些规则,我不能告诉你。如果它在这方面遵守标准,那么它就会遵守。然而,我可以想象,使用虚拟、dll和不同TU的组合可能会有问题。我从来没有测试过,但我相信没有问题。

    f.h :

    struct f {
        // inline required here or before the definition below
        inline void g();
    };
    
    void f::g() { ... }
    

    C99

    内联定义 必须 也是 另一个翻译单元中包含的整个程序中的外部定义。理由(引用PDF解释C99几个功能背后的理由):

    C99中的内联确实以两种方式扩展了C++规范。首先,如果一个函数在一个翻译单元中内联声明,则不需要在其他每个翻译单元中都内联声明。例如,这允许将库函数内联到库中,但只能通过其他地方的外部定义使用。为外部函数使用包装器函数的替代方案需要一个额外的名称;如果翻译器实际上不进行内联替换,也可能对性能产生不利影响。

    测试小型C++代码段是否符合标准的一个好地方是 comeau online compiler 如果它被拒绝了,人们可以很确定它不是严格符合标准的。

        2
  •  7
  •   Fabio Ceconello    12 年前

        3
  •  4
  •   Uri    16 年前

        4
  •  3
  •   dirkgently    16 年前

    […]链接器可能会“选择”任意目标文件作为定义的源。

    编辑: 任何 实际杠杆。我所说的实用性,是指即使实现方式略有不同。

    允许有多个定义 inline 功能:

    3[…]内联函数应在使用它的每个翻译单元中定义。

    这意味着该函数将在每个编译单元中定义[…]

    2带有内联说明符的函数声明(8.3.5、9.3、11.4)声明内联函数。内联说明符向实现表明,在调用点内联替换函数体比通常的函数调用机制更可取。在调用点执行此内联替换不需要实现;然而,即使省略了这种内联替换,其他规则 对于7.1.2定义的内联函数,仍应遵守。

    82)内联关键字对函数的链接没有影响。 § 7.1.2 138

    4内联函数应在使用它的每个翻译单元中定义,并且在每种情况下都应具有完全相同的定义(3.2)。[注意:在内联函数的定义出现在翻译单元中之前,可能会遇到对内联函数的调用。end Note]如果函数的定义在首次声明为内联之前出现在翻译单位中,则程序格式不正确。如果具有外部连杆的功能是

    未定义

    至于 virtual

    标准规定:

    • 必须可用
    • 一个定义

    MSDN :

    你的 A.h 包含类定义和成员 foo()

    U1.cpp U2.cpp 两者 定义 两个不同 物体 A .

    您创建了另一个 A. main() 这很好。

    到目前为止,我只看到了一个定义 A::foo() 总是

        5
  •  2
  •   Scott Stanchfield    16 年前

    如果你想确保函数被编译到特定的库中,不要内联它们。