2011-05-01 192 views
0

好吧,直到现在,我认为在头文件中定义的函数被视为内联函数,就像模板的东西,一次定义一样。为什么我明确地必须在这里声明函数?

我也使用包含守卫,但我仍然有多个定义的对象的链接器错误,我知道这是因为所有这些不同的单位重复的东西链接器试图挑选哪个项目是正确的。

我也知道,内联仅仅是一个建议,甚至可能没有得到由编译器使用等

然而,我必须明确地定义那个小头所有这些小功能,唯一的工具,我写。

即使函数很大,我也不得不声明它们是内联的,编译器仍然可能忽略这个提示。但是我不得不这样定义它们。

实施例:

#ifndef texture_math_h__ 
#define texture_math_h__ 

float TexcoordToPixel(float coord, float dimension) 
{ 
    return coord * dimension; 
} 

float PixelToTexcoord(float pixel, float dimension) 
{ 
    return pixel/dimension; 
} 

float RecalcTexcoord(float coord,float oldDimension, float newDimension) 
{ 
    return PixelToTexcoord(TexcoordToPixel(coord,oldDimension),newDimension); 
} 
#endif // texture_math_h__ 

错误是,在xxx.obj已经定义,对于每个包括所述文件

当我声明所有那些行内的单位布拉布拉,它正确地链接。

这是什么原因?这不是一个巨大的问题,而且,优化可能是内联在cpp中找到的东西,对吧?

我只是好奇为什么在这里,希望它不是太多的重复,并感谢您的时间。

+1

您能否提供一个代码示例? – 2011-05-01 09:48:54

+1

http://www.parashift.com/c++-faq-lite/inline-functions.html – Anycorn 2011-05-01 09:51:57

+0

@Anycorn:那么'auto'内联shtick只适用于类成员函数,而不是常规函数呢? – Erius 2011-05-01 09:56:08

回答

4

包含警卫只防范代码被包含两次相同翻译单元。因此,如果您有多个包含相同标题的文件,则代码将包含多次。在头文件中定义的函数默认不是内联的,所以这会给你链接器错误 - 你需要用inline关键字定义这些函数,除非它们是类的成员函数。

另外,请注意,包含双下划线的名称是为C++实现而保留的 - 您不能在自己的代码中创建这样的名称。

+0

好的,谢谢你的帮助。我认为这暗示着内联的东西超越了类。干杯!编辑:那些ifdef名字来自视觉辅助x的'包围守卫'功能。我不会用这个惯例来表达我自己的名字,是的。关于双下划线的 – Erius 2011-05-01 10:02:36

+0

:这不仅适用于标识符的开头吗? – MFH 2011-05-01 10:03:48

+0

@MFH不,这是单个下划线,后跟一个大写字母,如果在全局范围内使用,则后跟任何内容。 – 2011-05-01 10:05:20

1

成员函数有潜力内联 - 你不能强制内联! - 如果(a)它们是在类中定义的,或者(b)在定义中使用了inline子句。请注意,如果您使用的内联子句不应该定义头中的函数 - 唯一的例外是模板,因为它们是“特殊的”。
正如你刚才更新的问题:
这个头的每个用户将有一个函数定义 - >多个定义。你需要单独定义和声明!

+0

我明白了,所以我在这里实际上运动风格很差?仍然绿色和所有。 – Erius 2011-05-01 09:59:34

+0

为什么你不应该在头文件中定义函数?这是inline关键字的主要目的! – 2011-05-01 10:01:43

+0

还有那个。我一直认为,如果在'.cpp'中定义内联函数而不是'.h',那么在大多数情况下,编译器将不能**内联你的函数(导致它无法访问它的实现)。 – beduin 2011-05-01 10:05:12

1

这一切都是关于的一个定义规则。这表明您只能在链接到该程序的所有翻译单元的C++程序中为每个非内联函数(以及各种其他类型的实体)定义一个定义。

标记功能inline使通常的的例外情况成为一个定义规则。它声明(换言之)如果所有定义都匹配,并且在使用内联函数的每个翻译中都提供了定义,则每个翻译单元可以有一个内联函数的定义。

通过包含多次包含定义的头文件,包含防护将防止您意外地为每个翻译单元提供多个定义。

要满足对于非内联函数的一个定义规则,您仍然必须确保只有一个包含函数定义的翻译单元。通常的做法是只通过声明头文件中的函数并使用包含定义的单个源文件。

相关问题