缘由
老代码出现新问题,链接时出现问题。
/tmp/ccODJt0B.o: In function `main':
b.cpp:(.text+0x15): undefined reference to `A::GetAttr(int)'
collect2: error: ld returned 1 exit status
复现
简化代码复现如下:
//a.h
struct A
{
public:
int GetAttr(int i);
};
//a.cpp
#include "a.h"
inline int A:: GetAttr(int i)
{
return 0;
}
//b.cpp
#include "a.h"
int main()
{
A a;
a.GetAttr(0);
return 0;
}
//gcc -o a.o -c a.cpp
//gcc -o b b.cpp a.o
分开实现实现,为了提高性能,直接加inline措施不正确。如果函数长期没有使用,不会报错,遇到使用时会出现上述的链接错误。
以下两种方式都不正确:
- 情况1: a.h加inline, a.cpp也加inline: b.cpp看到的GetAttr声明为inline,所以要求GetAttr必须定义在b.o内,即违反了cpp手册中如下要求:
The definition of an inline function or variable (since C++17) must be present in the translation unit where it is accessed (not necessarily before the point of access). - 情况2: a.cpp加inline, .h不加, b.cpp看到的GetAttr声明非inline,但是a.cpp里实现的GetAttr实际为inline,因此违反了cpp手册里如下要求:
An inline function or variable (since C++17) with external linkage (e.g. not declared static) has the following additional properties:
It must be declared inline in every translation unit.
即a.cpp里的GetAttr实际是inline function, 且不是static,所以必须在每个.o的视角中都是声明为inline,但是实际上b.cpp看到的是声明为非inline的
小结
inline 必须实现在头文件,对引用可见。