当我们在Java、Vala或C#中设计类时,我们将定义和声明放在同一个源文件中。但在C++中,传统上更喜欢将定义和声明分开放在两个或多个文件中。
如果我只使用头文件并把所有内容都放在里面,像Java那样,会发生什么?会有性能惩罚或其他问题吗?
当我们在Java、Vala或C#中设计类时,我们将定义和声明放在同一个源文件中。但在C++中,传统上更喜欢将定义和声明分开放在两个或多个文件中。
如果我只使用头文件并把所有内容都放在里面,像Java那样,会发生什么?会有性能惩罚或其他问题吗?
#ifndef Include_Guard
#define Include_Guard
class MyClass {
public:
void DoSomething() {
/* ... code goes here ... */
}
};
#endif
那么您就不会冒着破坏ODR的风险。如果您将此重写为
#ifndef Include_Guard
#define Include_Guard
class MyClass {
public:
void DoSomething();
};
void MyClass::DoSomething() {
/* ... code goes here ... */
}
#endif
如果你不将成员函数标记为inline,并且多个客户端#include
此文件,则会违反ODR,因此你会打破ODR规则。
所以总结一下-为了避免违反ODR规则,你应该将类拆分为.h/.cpp对。但是,如果你正在编写类模板,则不需要.cpp文件(可能根本不应该有),如果你可以标记类的每个成员函数为inline,也可以避免使用.cpp文件。
将定义放在头文件中的缺点如下:
头文件A - 包含方法A()的定义
头文件B - 包含头文件A。
现在假设您更改了方法A的定义。由于头文件A包含在B中,因此您需要编译文件A和B。
将所有内容放在头文件中存在两个特定的问题:
编译时间会增加,有时甚至会大幅增加。C++的编译时间已经足够长了,这不是你想要的。
如果实现中存在循环依赖,将所有内容都放在头文件中会变得困难或不可能。例如:
header1.h
struct C1
{
void f();
void g();
};
header2.h
struct C2
{
void f();
void g();
};
impl1.cpp
#include "header1.h"
#include "header2.h"
void C1::f()
{
C2 c2;
c2.f();
}
impl2.cpp
#include "header2.h"
#include "header1.h"
void C2::g()
{
C1 c1;
c1.g();
}
class Foo;
。这是一个类的定义:class Foo { void foo(); int bar(const char*);};
。在C++中,通常将类的定义放在头文件中,需要决定的是在哪里放置成员函数的定义。 - Steve Jessop