C++头文件定义全局函数或类成员函数

C++头文件定义全局函数或类成员函数

你可能很熟悉C/C++的声明定义规则:

头文件中声明变量和函数,源文件中定义变量和函数。在头文件中定义变量和函数会导致“重定义”,
因为包含该头文件的不同元文件将创建变量或函数的多个副本,这些副本都具有"extern”的可见性,
必然会造成冲突。

上述认知在你第一次接触到模板类时受到了冲击:模板类的实现都在头文件内。

接着你还接触到了所谓的"HeaderOnly"库,他们只包含头文件,没有源文件。

为什么定义可以都写在头文件里而没有造成“重定义”错误呢?在讲清楚这个问题之前,你需要回顾下
line关键字。

line修饰的函数称为内联函数,他告诉编译器允许将函数在调用位置展开,而不使用函数调用。优点是
可以减少函数调用的开销,副作用是会导致代码体积增加,因为每个调用位置都会复制一遍。

事实上,现代编译器已经十分智能,他会自动选择是否需要将函数内联,即使你没有用inline修饰。反之,
即使用了inline,编译器也不一定会内联。既然这样,inline关键字似乎可以删掉了,之所以还保留到现在,
是因为他的附加特性“允许存在多个副本”还有用。

inline修饰的函数可以存在多个副本,所以你可以在头文件中用inline定义一个全局函数,然后在多个源文件
中调用而不用担心造成“重定义”错误,编译器会保证他们都使用同一个定义(相同的函数地址)。甚至这些
定义可以有不同的实现,不过这属于未定义行为,编译器可能随即选择一个。

所以现在的inline关键字实际上起到的是类似multiple的作用。

C++中,类声明中直接定义的成员函数,都被当从inline函数,所以不会造成“重定义”,这解释了文章开头的
问题。模板有一点不同,但有一点类似。模板由于存在不同的模板参数,天然存在多个不同定义,所以编译器
负责自动选择合适的定义,并不会认为是“重定义”。

现在,你也可以写一个HeaderOnly的库了:

  • 使用inline修饰全局函数。
  • 使用类成员函数。
  • 使用模板。

你可能感兴趣的:(C/C++,c++,开发语言)