考虑以下四个成员函数声明和定义:
// ==== file: x.h
#ifndef X_H
#define X_H
class X {
public:
int a(int i) { return 2 * i; }
inline int b(int i) { return 2 * i; }
int c(int i);
int d(int i);
};
inline int X::c(int i) { return 2 * i; }
int X::d(int i) { return 2 * i; }
#endif
Run Code Online (Sandbox Code Playgroud)
为了完整性,这里是实例化X并调用方法的.cpp文件...
// ==== file: x.cpp
#include "x.h"
#include <stdio.h>
int main() {
X x;
printf("a(3) = %d\n", x.a(3));
printf("b(3) = %d\n", x.b(3));
printf("c(3) = %d\n", x.c(3));
printf("d(3) = %d\n", x.d(3));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的问题:这四种方法之间是否存在显着差异?我从这篇文章的评论中了解到,编译器可以自动内联在类定义中定义的方法.
许多答案都假设我在询问内联与否之间的区别.我不是.正如我在原始帖子中提到的,我理解在头文件中定义方法会给编译器许可证内联方法.
我也(现在)理解方法d的风险如下所示:因为它没有内联,所以如果有多个翻译单元,它将被多重定义.
我的问题仍然存在:四种方法之间是否存在显着差异?(如上所述,我知道方法d不同).但是 - 同样重要的是 - 是否有风格或惯用的考虑因素会让开发人员选择其中一个?
由于这个答案不断得到提升,我觉得有必要改进它.但我正在添加的大部分内容已在其他答案和评论中说明,而这些作者应该得到赞誉.
关于将函数体放在类定义中还是在它下面(但仍然在头文件中)之间是否有区别的问题,有三种不同的情况需要考虑:
1)该函数不是模板,并且未声明为内联函数.在这种情况下,它必须在类定义或单独的cpp中定义,否则只要尝试将h包含在多个编译单元中,就会出现链接器错误.
2)该函数是一个模板,但不是内联声明的.在这种情况下,将主体放在类定义中会向编译器提示可以内联函数(但最终决定仍由其自行决定).
3)该函数声明为内联.在这种情况下,没有语义差异,但有时可能需要将函数体放在底部以适应依赖循环.
原始答案,提供了良好的信息,但没有解决实际问题:
您已经注意到了内联差异.此外,在标题中定义成员函数意味着您的实现对每个人都可见.更重要的是,这意味着包含标题的每个人都需要包含使您的实现工作所需的所有内容.
| 归档时间: |
|
| 查看次数: |
1269 次 |
| 最近记录: |