内联方法:缺点

时间:2013-02-19 11:02:46

标签: c++ inline

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

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...
}

Main.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)" (??0LivingBeing@@QAE@N@Z) already defined in Forest.obj
1>main_test.obj : error LNK2005: "public: void __thiscall LivingBeing::breathe(void)" (?breathe@LivingBeing@@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文件中使用这些方法。通过更改源文件我有什么风险?

非常感谢

2 个答案:

答案 0 :(得分:4)

您正在标题中定义函数(LivingBeing::LivingBeingLivingBeing::breathe),这意味着每个翻译单元中都会有一个包含该标题的定义。这打破了一个定义规则(ODR),因此链接错误。

您有三种选择:

  • 将函数定义移动到源文件中,因此它们只定义一次;或
  • 声明它们inline以允许多个相同的定义;或
  • 移动类定义中的定义,隐式地使它们成为inline
  

内联方法的缺点是什么?

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

答案 1 :(得分:0)

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