在.cpp文件中的C ++内联成员函数
我知道定义的内联成员函数应该进入标题。 但是如果把函数的实现放到头文件中呢? 我们来看看这种情况:
档案啊
#pragma once #include "Bh" class A{ B b; };
文件Bh
#pragma once class A; //forward declaration class B{ inline A getA(); };
由于通知包括我必须把执行getA
到
B.cpp
#include "Bh" #include "Ah" inline AB::getA(){ return A(); }
编译器会内联getA
吗? 如果是这样,哪个inline关键字是重要的(头文件或者.cpp文件中的那个)? 有没有另一种方法将内联成员函数的定义放入它的.cpp文件中?
引用C ++ FAQ :
注意:函数的定义({…}之间的部分)必须放在头文件中,除非该函数仅用于单个.cpp文件。 特别是,如果将内联函数的定义放入一个.cpp文件,并从其他.cpp文件中调用它,则会从链接器中收到“无法parsing的外部”错误。
编译器只要发现任何内联函数的使用,就需要查看内联函数的定义 。 如果内联函数放置在头文件中,那通常是可能的。
编译器会内联getA吗?
不,除了使用getA()
在B.cpp本身。
如果是这样,那么哪个inline关键字是重要的(头文件中的还是cpp中的那个)?
最佳做法 :只在class级体外定义。
有没有另一种方法将内联成员函数的定义放入它的cpp文件中?
不,至less我不知道。
它不能超出B.cpp的范围。 编译器在每个编译单元的基础上运行,也就是编译每个.cpp文件,所以如果它编译C.cpp,它将不具有可用的getA()代码,并且需要执行一个函数调用,让链接器修正它(或者,如果它真的把你的单词和尝试内联,它将以链接器错误结束, inline
具有与static
类似的质量)。
唯一的例外是LTCG,也就是链接时代码的生成,它可以在更新的编译器上使用。
在这种情况下的一种方法是有另一个头文件(有时名为* .inl文件)包含内联的代码。
编辑:至于哪个内联是相关的 – 这是在类定义,即在头文件中的一个。 请记住,许多编译器对可以并应该内联的内容有自己的想法。 例如gcc可以完全禁用内联(-O0),或者它可以内联它认为值得内联的任何内容(如-O3)。
我会从相反的方向去解决这个问题。
不要将内联声明添加到你的函数中(除非你也需要)。
唯一需要将内联声明添加到函数/方法的方法是,如果在头文件中但在类声明之外定义该函数。
XH
class X { public: int getX() { return 4;} // No inline because it is part of the class. // The compiler knows that needs an inline tag int getY(); int getZ(); }; inline int X::getY() { return 5;} // This needs to be explicitly declared inline. // Otherwise the linker will complain about // multiple definitions in compilation units.
X.cpp
// Never declare anything inline in the cpp file. int X::getZ() { return 6; }
给你更具体的情况。
删除所有内联规范。 他们没有做你认为他们在做的事情。
现在,大多数编译器可以在链接时执行内联,也可以编译时间。 如果你的函数可能从内联中受益,那么链接时间优化器就可以做到这一点。
在链接器到达它的时候,编译器输出的内联状态并不多,只是编译器会将某些对象标记为可收集的,例如因为内联函数或类模板实例出现在多个编译单元中,或者当多个符号共享一个名字时,应该引发一个错误,比如主函数被定义了两次。 这些都不会影响它将生成的实际代码。
这是我做到的。
档案啊
#pragma once #include "Bh" class A { B b; };
文件Bh
#pragma once class B { public: template<class T> inline T getA() { assert(NULL); // Use 'getA<A>()' template specialization only! return NULL; } }; class A; // Forward declaration template<> inline AB::getA<A>();
文件Ch
#pragma once #include "Ah" #include "Bh" // Implement template specialization here! template<> inline AB::getA<A>() { return A(); }
只要包含“Ch”文件即可使用getA()方法。 原始代码的唯一变化是getA()方法必须定义为public而不是private。
但是,正如你们许多人所解释的那样,这并不是很有用。