开发者

c++ #include style differences

开发者 https://www.devze.com 2023-03-10 10:39 出处:网络
So the other day, I was looking through some old C++ books and noticed a way of creating a C++ class I had never seen before.Everything I have seen up to that point had always used the #include \"head

So the other day, I was looking through some old C++ books and noticed a way of creating a C++ class I had never seen before. Everything I have seen up to that point had always used the #include "header.h" and compiled the implementation files separately. What I saw the author of this book do is actually put an include directive to the implementation at the end of the header file and omitting the .cpp file from the compilation. Has anybody used this style?

For Example: I have main.cpp employee.h employee.cpp

//main.cpp
#include <iostream>
#include <stdio.h>
#include <string>
#include "employee.h"
void main()
{/*some code*/}  

//employee.h
#ifndef EMPLOYEE_H
#define EMPLOYEE_H
class employee
{
   public:
   //public members
   private:
   //private members
}
#endif

//employee.cpp
#include "employee.h"
#include <string>
//public member definitions

I would normaly compile this project like so:

g++ main.cpp employee.cpp

But in the author's example is like this

//main.cpp
#include <iostream>
#include <stdio.h>
#include <string>
#include "employee.h"
void main()
{/*some code*/}  

//employee.h
#ifndef EMPLOYEE_H
#define EMPLOYEE_H
class employee
{
   public:
   //public members
   private:
   //private members
}
#include "employee.cpp"  // <-- the line of code that caught my attention
#endif

//employee.cpp
 #include <string>
//public member definitions

And the resulting code compiles as

g++ main.cpp

Is this merely a style preference or are there any real benefits in this? I would think it wouldn't scale very well, but I am not a s开发者_JAVA技巧uper proficient C++ programmer either.


Doing this will bring the definition of the class in to every translation unit where the header file is included. This is a very unusual paradigm, and could be hazardous to your coding health. In particular, if you have main.cpp and foo.cpp both of which #include "employee.h", then all the methods on employee will be defined twice, which is a violation of the One Definition Rule and will create linker errors. In order to resolve those linker errors, you need to either move the definitions to their own translation unit, or mark them inline (which may or may not work).

This is however a useful idiom in some instances. Particularly with templates, which must be defined within the translation unit. In that case, when you want the declaration and implementation in separate files for readability, you can do an end-of-file #include. When I do this, I use a special file extension, .hpp to signify that the file is special in that it is not intended to be compiled on its own. See this answer for an example.


That approach is sometimes used when providing templates, and is equivalent to providing the template and implementation all in the header file, but allows humans to read the template declarations without going over the code. Equivalently, if you are providing inlined functions, it would be understandable (not going as far as recommended, but understandable) if you did the same.

For anything else, it is a bad approach. It not only requires all translation units to actually compile all of the function definitions, but it also requires you to declare all functions as inline, or include the header from a single translation, as otherwise it would trigger linker errors.


This is probably not a mainstream book. Anyway, if we define correctness by the condition of "it compiles", then yes, it is a matter of style, and both styles are correct.

However, the only truly correct style, according to the standard, and design guidelines that match other programming languages, is the first one, matching the spirit of separate compilation of translation units. As you yourself said, the second style would not scale very well.

Another point would be that #include <stdio.h>, which is not standard any more:

#include <cstdio>


This will certainly work, but it has a couple of downsides:

  • Longer compilation times - normally if you change one file, you only need to compile that one file and the linker will combine it with the other older compilation results. When everything is included into a single file, everything needs to be recompiled at once.
  • Potential namespace collision - any symbols declared in one module are now visible to all of them. This can be a big problem if you use any macros.


This is actually a trick I have seen in build systems where for nightly builds to speed them up, including all cpp file in one and them compiling it can generate some big gains in overall speed.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号