2013-02-19 66 views
1

我有一个关于内联方法的问题。 我正在使用为碰撞模型开发的库。一个负责图形界面的头文件包含函数的声明和实现,但函数没有内联。因此,将这些功能包含在几个翻译单元中是不可能的。 如这里的说明是伪代码我设计来加以说明:内联方法:缺点

LivingBeing.h

#ifndef LIVINGBEING_H 
#define LIVINGBEING_H 

class LivingBeing 
{ 
public: 
    LivingBeing(double _size); 
    void breathe(); 
private: 
    double size; 
}; 
////////////// 

LivingBeing::LivingBeing(double _size) 
{ 
    size = _size; 
} 
void LivingBeing::breathe() 
{ 
    // do something 
} 
#endif 

Forest.h

#ifndef FOREST_H 
#define FOREST_H 

#include "LivingBeing.h" 

class Forest 
{ 
public: 
    Forest(int _numberLivingBeings); 
private: 
    int numberLivingBeings; 
}; 

#endif 

Forest.cpp

#include "Forest.h" 

Forest::Forest(int _numberLivingBeings) 
{ 
    numberLivingBeings = _numberLivingBeings; 
      // Call LivingBeing constructor, methods etc... 
} 

主。 cpp

#include "Forest.h" 

int main() 
{ 
    Forest forest = Forest(10); 
    return 0; 
} 

此代码不会编译,除非在构造函数LivingBeing和方法呼吸前添加inline关键字。错误信息是:

1>main_test.obj : error LNK2005: "public: __thiscall LivingBeing::LivingBeing(double)" ([email protected]@[email protected]@Z) already defined in Forest.obj 
1>main_test.obj : error LNK2005: "public: void __thiscall LivingBeing::breathe(void)" ([email protected]@@QAEXXZ) already defined in Forest.obj 
1>C:\Users\******\Documents\Visual Studio 2010\Projects\TutorialChronoEngine\Debug\Test_3.exe : fatal error LNK1169: one or more multiply defined symbols found 

我的问题是:内联方法的缺点是什么?我使用的真正的库非常大,我想从特定文件(在我的示例中它将是LivingBeing.h)内联方法,以便可以在几个.cpp文件中使用这些方法。我通过更改源文件来冒着什么风险?

非常感谢

+0

记住了'inline'关键字 - 如果有的话 - 只是一个提示编译器(内联函数体),以及现代的编译器/连接器可以在链接时内嵌的事情。 – PlasmaHH 2013-02-19 11:38:55

+0

使用'inline'关键字的**优势是代码可能工作。如果许多函数看起来像“LivingBeing :: LivingBeing(double _size){size = _size;结果程序会更小,运行速度更快。 – 2013-02-19 12:11:03

回答

4

您在报头中定义的功能(LivingBeing::LivingBeingLivingBeing::breathe),这意味着将有在每个转换单元,其包括报头中的定义。这打破了一个定义规则(ODR),因此链接错误。

你有三个选择:所以他们只定义一次

  • 移动功能定义为源文件;或
  • 声明它们为inline以允许多个相同的定义;或
  • 移动类定义中的定义,这隐含地使它们成为inline

内联方法的缺点是什么?

  • 可能增加编译时间和可执行文件大小;但你需要测量一下是否有任何明显的差异。
  • 每当任何内联函数发生更改时,不太稳定的API - 客户端代码将需要重新编译。
  • 意外打破ODR的可能性,例如,如果一个函数包含的宏可能在不同的翻译单元中有不同的扩展。
+0

非常感谢您的回答。我认为最安全的选择是将函数定义移动到一个源文件中,但是,这些文件非常大,我可能必须为多个.h文件执行此操作。内联是更快,但我想知道如果我可能冒险增加编译时间,或其他问题,我可能没有想到... – Vincent 2013-02-19 11:10:02

0

仅仅因为在“源”文件(.c/.cpp)中定义的方法并不意味着它不会被内联......链接时操作可以执行该优化。相反,仅仅因为一个方法在头文件中声明并实现为内联并不意味着它将被内联。一般来说,如果头文件中的方法非常简单,例如在头文件中定义, int getWidth() const { return width; },或MyObj* getNext() { return internal_itor ? internal_itor->next : 0; }

+0

感谢您的答案。然后,如果我理解正确,编译器内联或不自动的一些功能。 inline关键字将作为编译器的提示。它将确保我的代码在需要内联时编译(以确保它不会破坏ODR),但我不会冒太大风险,可能会产生额外的编译时间和可移植性问题 – Vincent 2013-02-19 16:22:10