•该函数将内联;也就是说,编译器将尝试在每个调用点为函数生成代码,而不是使用函数调用指令来使用通用代码。对于像month()这样几乎什么都不做的函数来说,这可能是一个显著的性能优势被大量使用。
•无论何时更改内联函数体,该类的所有使用都必须重新编译。如果函数体不在类声明中,则只有在类声明本身发生变化时才需要重新编译users。不重新编译时,主体
•类定义变大。因此,很难在成员函数定义中找到成员。
我不知道这本书在这一点上到底想说什么。我们所说的"必须重新编译"是什么意思?并且只有当类声明本身发生变化时才需要重新编译"无论何时更改内联函数体,该类的所有使用都必须重新编译。如果函数体不在类声明中,则只有在类声明本身发生变化时才需要重新编译users。不重新编译时,主体
我想,从上下文中,引用的部分讨论的是优点& &;将成员定义放在类声明内的缺点。
假设你有X
类。你必须在某个地方申报。在典型的场景中,它将被放置在头文件中,头文件的唯一作用是保存此声明。我们称之为x.h
。
x.cpp
)。
解决方案1:
// file x.h contains everything
class X
{
public:
X() { std::cout << "X() has been hitn"; }
};
解决方案2:
// file x.h contains only the declaration(s)
class X
{
public:
X();
};
// file x.cpp contains the class member definitions
#include "x.h"
X::X() { std::cout << "X() has been hitn"; }
无论您使用哪种解决方案,您肯定有一些使用您的类的代码,并且通常它位于不同的源文件中,例如:
// main.cpp
#include "x.h"
int main()
{
X x;
}
首先要注意的是:无论选择解决方案1还是2,用户(这里是:main.cpp
)看起来都是一样的。这太棒了。现在,Bjarne想要告诉你的消息是:考虑类代码的更改将如何影响用户。
解决方案1您已经将所有内容打包到头文件中。对类的任何更改,即使是像添加新成员函数或只是更改类格式(您知道,制表符、空格等)或添加注释这样看似无害的更改,也会迫使编译器重新编译main.cpp
。为什么?专业的c++程序由许许多多的源文件组成,它们的编译由特殊的实用程序控制和执行,如cmake
、make
等。它们只是查看组成程序的文件的时间戳。任何更改都是重新编译的信号。头文件永远不会被编译,但是所有包含它们的源文件(= *.cpp)(甚至间接地,通过其他头文件)都必须被重新编译。这解释了这个:
无论何时更改内联函数体,该类的所有使用都必须重新编译。
(只是为了确定:默认情况下,在类声明内部声明的所有类成员函数都被视为inline
)。这里,main.cpp
是一个"使用"的例子。上面提到的。
方案2,文件main.cpp
将被重新编译,只有当x.h
已经改变(以任何方式)。如果程序员只接触x.cpp
,那么main.cpp
将不会被重新编译,因为(a) c++被设计成允许这样做,(b)专业的c++程序使用其他程序(我在上面提到过)来促进大型c++程序的有效编译。明确地说:它们不是使用像g++ *.cpp
这样的命令编译的,这些命令可以在一些介绍c++的教科书中找到。
最后一点。引入inline
关键字主要是为了允许解决方案1。方案二是原C语言的方式。解决方案1有时在c++中用于更好的性能(但现代编译器在许多情况下可以在没有它的情况下完成相同的工作),并且经常用于模板(这在C中是不存在的)。解决方案1是最常见的模板编程方式,解决方案2是典型的"普通";成员函数。Bjarne所写的对于库的设计者来说是非常重要的,我希望现在你明白为什么了。