在头文件与实现(.cpp)文件中定义构造函数 [英] Defining constructor in header file vs. implementation (.cpp) file

查看:835
本文介绍了在头文件与实现(.cpp)文件中定义构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可以在类 .h 文件或实现文件 .cpp 中定义类构造函数的主体。就特定项目中的编译器而言,这两种样式可能是相同的(对我而言,项目表示 DLL )。
确实适用于任何成员函数:它们可以在头文件中定义,也可以在其中声明,然后在cpp文件中定义。

I can define the body of a class constructor in the class .h file or in the implementation file .cpp. These two styles are probably identical as far as the compiler is concerned within a specific project (project for me means DLL). Same applies to any member functions really: they can be defined in the header file or just declared there and then defined in the cpp file.

但是,我发现,如果我需要在不同的项目中包含此类类头文件(这意味着最终使用该头文件的代码会以不同的 DLL ),然后在头文件中进行实际实现会在编译时造成一些麻烦(而不是链接...我什至没有意识到)。
为什么?好吧,我不会做过多的详细介绍,但是编译器显然会尝试解决所有可能在其他头文件等中定义的功能,从而迫使可怜的开发人员开始提取各种头文件等。

However, I found that if I need to include such class header file(s) in different projects (meaning that ultimately the code that uses the header file ends up in a different DLL) then having the actual implementation in the header file causes some headaches at compilation (not at linking... I don't even get to that point). Why? Well I won't go too much in detail but the compiler obviously tries to resolve all the functions which might be defined in other header files etc., forcing the poor developer to start pulling in various header files etc.

总是最好不要让头文件没有任何实现,而只是将它们用于声明吗?这将使它们更容易地包含在多个项目中,而不必携带很多额外的垃圾。

Isn't it always best to keep header files free of any implementation and just use them for 'declarations'? That would make it easier to include them in more than one projects w/o having to carry around a lot of extra junk.

您对此有何看法?

推荐答案

一个重点需要注意的是,如果成员函数是在头文件中定义的,则它必须在类主体中,或者必须显式标记为 inline 。换句话说,在头文件中执行此操作是完全错误的:

One important point to note is that if a member function is defined inside a header file, it must be either inside the class body or it must be marked explicitly as inline. In other words, it is plain wrong to do this in a header file:

class A {
  public:
    A();
};

A::A() {
  // constructor body
}

这是错误的原因是因为它将使编译器在每个编译单元中包含该定义,而很显然任何函数都必须仅定义一次。以下是做同一件事的正确方法:

The reason it's wrong is because it will make the compiler include the definition in each compilation unit, while it's obvious that any function must be defined only once. Here are correct ways to do the same thing:

class A {
  public:
    inline A();
};

inline A::A() {
  // constructor body
}

或:

class A {
  public:
    inline A() { // inline isn't required here, but it's a good style
     // constructor body
    }
};

在两种情况下,构造函数都是内联的。使其成为常规离线功能的唯一正确方法是在实现文件中而不是在标头中定义它。这是这两种方法之间最重要的区别。

In both cases the constructor is inline. The only correct way to make it a regular out-of-line function would be to define it in the implementation file, not in the header. This is the most important difference between these two approaches.

现在,值得注意的是,内联是一种优化。与优化一样,最好避免它们,直到证明有必要为止。内联会导致其他问题,其中包括兼容性问题:如果更改未内联的函数的主体,则只需要重新编译定义它的单元,每个人都立即开始使用新的实现。使用内联函数,您需要重新编译包含相关标头的每个单元,这可能会很麻烦,尤其是如果标头是由不同的人在不同项目中使用的。

Now, it is worth noting that inlining is an optimization. And as always with optimizations, they are best avoided until proved necessary. Among other problems inlining can lead to, there is the compatibility problem: if you change the body of a function that is not inlined, you only need to recompile the unit where it is defined, and everyone starts using the new implementation right away. With inlined functions, you need to recompile every unit that includes the relevant header, which can be a pain, especially if the header is used across different projects by different people.

换句话说,请尽可能使用常规的脱机定义,直到通过性能分析证明特定的函数调用是性能瓶颈为止。此规则唯一合理的例外是琐碎的setter和getter,即使使用它们,也要格外小心-有一天它们可能变得很琐碎,这将意味着大量的重新编译和兼容性破坏。

In other words, use regular out-of-line definitions wherever possible until it is proved by profiling that a particular function call is a performance bottleneck. The only reasonable exception to this rule are trivial setters and getters, and even with them it is better to be careful - one day they may become non-trivial and it will mean a lot of recompilation and compatibility breaking.

这篇关于在头文件与实现(.cpp)文件中定义构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆