C++ 在 .h 文件或 .cpp 文件中实现类的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1809679/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between implementing a class inside a .h file or in a .cpp file
提问by Hyman
I was wondering which are the differences between declaring and implementing a class solely in a header file, compared with normal approach in which you protype class in the header and implement in effective .cpp file.
我想知道仅在头文件中声明和实现一个类与在头文件中定义类并在有效的 .cpp 文件中实现的正常方法相比有哪些区别。
To explain better what I'm talking about I mean differences between normal approach:
为了更好地解释我在说什么,我的意思是正常方法之间的差异:
// File class.h
class MyClass
{
private:
//attributes
public:
void method1(...);
void method2(...);
...
};
//file class.cpp
#include "class.h"
void MyClass::method1(...)
{
//implementation
}
void MyClass::method2(...)
{
//implementation
}
and a just-headerapproach:
和只是标题方法:
// File class.h
class MyClass
{
private:
//attributes
public:
void method1(...)
{
//implementation
}
void method2(...)
{
//implementation
}
...
};
I can get the main difference: in the second case the code is included in every other file that needs it generating more instances of the same implementations, so an implicit redundancy; while in the first case code is compiled by itself and then every call referred to object of MyClass
are linked to the implementation in class.cpp
.
我可以得到主要区别:在第二种情况下,代码包含在需要它生成更多相同实现实例的每个其他文件中,因此隐式冗余;而在第一种情况下,代码是自己编译的,然后每个引用对象的调用MyClass
都链接到class.cpp
.
But are there other differences? Is it more convenient to use an approach instead of another depending on the situation? I've also read somewhere that defining the body of a method directly into a header file is an implicit request to the compiler to inline that method, is it true?
但是还有其他区别吗?根据情况使用一种方法而不是另一种方法更方便吗?我还在某处读到过,将方法的主体直接定义到头文件中是对编译器内联该方法的隐式请求,这是真的吗?
回答by Steve Jessop
The main practical difference is that if the member function definitions are in the body of the header, then of course they are compiled once for each translation unit which includes that header. When your project contains a few hundred or thousand source files, and the class in question is fairly widely used, this might mean a lot of repetition. Even if each class is only used by 2 or 3 others, the more code in the header, the more work to do.
主要的实际区别在于,如果成员函数定义在头文件的主体中,那么它们当然会为包含该头文件的每个翻译单元编译一次。当您的项目包含数百或数千个源文件,并且所讨论的类使用相当广泛时,这可能意味着大量重复。即使每个类只被 2 或 3 个其他人使用,标题中的代码越多,要做的工作就越多。
If the member function definitions are in a translation unit (.cpp file) of their own, then they are compiled once, and only the function declarations are compiled multiple times.
如果成员函数定义在它们自己的翻译单元(.cpp 文件)中,那么它们被编译一次,并且只有函数声明被编译多次。
It's true that member functions defined (not just declared) in the class definition are implicitly inline
. But inline
doesn't mean what people might reasonably guess it means. inline
says that it's legal for multiple definitions of the function to appear in different translation units, and later be linked together. This is necessary if the class is in a header file that different source files are going to use, so the language tries to be helpful.
确实,在类定义中定义(不仅仅是声明)的成员函数是隐式的inline
。但inline
并不意味着人们可能合理地猜测它意味着什么。inline
说函数的多个定义出现在不同的翻译单元中是合法的,然后再链接在一起。如果类位于不同源文件将要使用的头文件中,则这是必要的,因此该语言试图提供帮助。
inline
is also a hint to the compiler that the function could usefully be inlined, but despite the name, that's optional. The more sophisticated your compiler is, the better it is able to make its own decisions about inlining, and the less need it has for hints. More important than the actual inline tag is whether the function is available to the compiler at all. If the function is defined in a different translation unit, then it isn't available when the call to it is compiled, and so if anything is going to inline the call then it's going to have to be the linker, not the compiler.
inline
也是对编译器的提示,该函数可以有用地内联,但尽管名称如此,但这是可选的。你的编译器越复杂,它就越能自己做出关于内联的决定,它对提示的需求就越少。比实际的内联标记更重要的是该函数是否对编译器完全可用。如果函数是在不同的翻译单元中定义的,那么在编译对它的调用时它不可用,因此如果有任何东西要内联调用,那么它必须是链接器,而不是编译器。
You might be able to see the differences better by considering a third possible way of doing it:
通过考虑第三种可能的方法,您可能能够更好地看到差异:
// File class.h
class MyClass
{
private:
//attributes
public:
void method1(...);
void method2(...);
...
};
inline void MyClass::method1(...)
{
//implementation
}
inline void MyClass::method2(...)
{
//implementation
}
Now that the implicit inline is out of the way, there remain some differences between this "all header" approach, and the "header plus source" approach. How you divide your code among translation units has consequences for what happens as it's built.
既然隐式内联已经不存在了,这种“所有标头”方法和“标头加源”方法之间仍然存在一些差异。您如何在翻译单元之间划分代码会对构建时发生的情况产生影响。
回答by Ben S
Any change to a header that includes the implementation will force all other classes that include that header to recompile and relink.
对包含实现的头文件的任何更改都将强制包含该头文件的所有其他类重新编译和重新链接。
Since headers change less frequently than implementations, by putting the implementation in a separate file, you can save considerable compilation time.
由于头文件的更改频率低于实现,因此通过将实现放在单独的文件中,您可以节省大量编译时间。
As some other answers have already pointed out, yes, defining a method within a file's class
block will cause the compiler to inline.
正如其他一些答案已经指出的那样,是的,在文件class
块中定义方法将导致编译器内联。
回答by Naveen
Yes, the compiler will try to inline a method declared directly in header file like:
是的,编译器会尝试内联直接在头文件中声明的方法,例如:
class A
{
public:
void method()
{
}
};
I can think of following conveniences in separating the implementation in header files:
我可以想到以下在头文件中分离实现的便利:
- You'll not have code bloat because of the same code getting included in multiple translation units
- Your compilation time will reduce drastically. Remember that for any modification in the header file compiler has to build all other files which directly or indirectly include it. I guess it will be very frustrating for any one to build the whole binary again just for adding a space in the header file.
- 您不会因为多个翻译单元中包含相同的代码而导致代码膨胀
- 您的编译时间将大大减少。请记住,对于头文件中的任何修改,编译器都必须构建直接或间接包含它的所有其他文件。我想任何人为了在头文件中添加一个空格而再次构建整个二进制文件都会非常令人沮丧。
回答by AnT
Yes, defining methods inside class definition is equivalent to declaring them inline
. There's no other difference. There's no benefit in defining everything in header file.
是的,在类定义中定义方法等同于声明它们inline
。没有其他区别。在头文件中定义所有内容没有任何好处。
Something like that is usually seen in C++ with template classes, since template member definitions have to be included in header file as well (due to the fact that most compilers don't support export
). But with ordinary non-template classes there's no point in doing this, unless you really want to declare your methods as inline
.
类似的东西通常在带有模板类的 C++ 中看到,因为模板成员定义也必须包含在头文件中(因为大多数编译器不支持export
)。但是对于普通的非模板类,这样做是没有意义的,除非你真的想将你的方法声明为inline
.
回答by lalitm
For me, the main difference is that a header file is like a "interface" for the class, telling clients of that class what are its public methods (the operations it supports), without the clients worrying about the specific implementation of those. In sense, its a way to encapsulate its clients from implementation changes, because only cpp file changes and hence the compilation time is much less.
对我来说,主要区别在于头文件就像类的“接口”,告诉该类的客户它的公共方法(它支持的操作)是什么,而客户不必担心这些的具体实现。从某种意义上说,这是一种从实现更改中封装其客户端的方法,因为只有 cpp 文件更改,因此编译时间要少得多。
回答by jszpilewski
Once in the past I created a module shielding from differences in various CORBA distributions and it was expected to work uniformly on various OS/compiler/CORBA lib combinations. Making it implemented in a header file made it more easy to add it to a project with a simple include. The same technique guaranteed that the code was recompiled at the same time when the code calling it required recompilation when i.e. it was being compiled with a different library or on a different OS.
过去,我创建了一个模块,屏蔽了各种 CORBA 发行版中的差异,预计它可以在各种 OS/编译器/CORBA 库组合上统一工作。在头文件中实现它可以更容易地通过简单的包含将其添加到项目中。当调用它的代码需要重新编译时,即使用不同的库或在不同的操作系统上编译它时,相同的技术保证代码在同一时间被重新编译。
So my point is that if you have a rather tiny library that is expected to be reusable and recompilable across various projects making it a header offers advantages in integration with some other projects as opposed to adding extra files to the main project or recompiling an external lib/obj file.
所以我的观点是,如果你有一个相当小的库,预计它可以在各种项目中重用和重新编译,使它成为一个头文件在与其他一些项目集成方面具有优势,而不是向主项目添加额外的文件或重新编译外部库/obj 文件。