Do without the header files?

3

I'm seeing if I can do without tinkering with header files in C ++ projects. Probably they were the sea of good for C in the '60s, but actually today it is difficult to justify their existence in C ++.

I wrote a small program that consists of four files: main.cpp, file1.hpp, file2.hpp and file3.hpp Each header file has a class defined inside and this class consists of only one method. The characteristic is that in these headers there is the definition of the class, not just the declaration as usual.

The dependency between headers and the main can be seen in the following diagram:

And the sources are:

/*************/
/* file3.hpp */
/*************/
#pragma once

class HaceAlgo3
{
public:
// Estos atributos no se usan. Sólo están porque sí.
int iA;
float fB;

public:
  float calcula(float a, int b)
  {
    return a*b;
  }
};


/*************/
/* file2.hpp */
/*************/
#pragma once
#include "file3.hpp"

class HaceAlgo2
{
public:
  float calcula(float a, float b)
  {
    HaceAlgo3 ha;
    return ha.calcula(a,3) * b;
  }
};


/*************/
/* file1.hpp */
/*************/
#pragma once
#include "file2.hpp"

class HaceAlgo1
{
public:
  int calcula(int a, int b)
  {
    return a*b;
  }
};


/************/
/* main.cpp */
/************/
#include <iostream>
#include "file1.hpp"
#include "file3.hpp"
using namespace std;

int main()
{
  float fRta;

  HaceAlgo2 ha2;
  fRta = ha2.calcula(15.0, 20.0);
  printf("%f\n", fRta);

  HaceAlgo3 ha3;
  fRta = ha3.calcula(300.0, 2);
  printf("%f\n", fRta);

  return 0;
}

In main.cpp, the #include file3.hpp line is unnecessary, but when it is, and there are no redefinition errors and compile correctly, it would show in principle that programming in this way would not cause major problems.

Could there be some kind of error when working in this way on projects of several dozen files? Thank you very much for any response.

    
asked by msx68k 23.04.2018 в 05:01
source

2 answers

2

The C ++ header files are not compiled, only copy-paste into the code files to finally link all the symbols with the linker. Many of the people with experience in C ++ have lived and suffered the problems of the header files: as their tendency to lengthen the compilation times, to inflate the size of the code and to complicate the structure of any project.

For that and other reasons, the C ++ standards committee has been working on a system to get rid of files for years. of bedside and offer a modern alternative, more practical and less expensive at the process and use level: the modules .

Until the modules arrive, it is possible to dispense with the header files by renouncing the templates ( template ), using extern in an imaginative way and with great zeal and care about the definitions of symbols. But even if it is possible to do so, the resulting work is so tedious and complicated that you may end up touring your office armed with an ax and attacking all of your colleagues, the last thing you would see on your desk would be a source code with this text repeated thousands of times:

/* Mucho trabajo y poca diversión hacen de msx68k un tipo aburrido */

So you want to do without header files in C ++ ?: My advice is that you do not, despite their known problems are the best tool that (so far) we have and actually help (and much) to simplify and structure the source code.

  

In main.cpp , line #include file3.hpp is unnecessary, but being, and there are no errors of redefinition and compile correctly, it would show in principle that programming in this way would not cause major problems.

This is so because the #pragma once that avoids the double inclusion of file3.hpp , of not having used that extension of MSVC you should have created a inclusion log , which incidentally is what I advise you to use since #pragma once is not portable.

Even though line #include file3.hpp is unnecessary, my advice is to keep it; the reason is that the inclusions give additional information to the code informing the reader of the needs of the subsequent code; only a person familiar with file2.hpp would know that this header includes file3.hpp but you can not assure beforehand that other programmers know file2.hpp (and therefore know that they can do without file3.hpp ), maintaining the inclusion of file3.hpp you clearly and accurately report the dependencies of your code (obviously it can be done badly and be more confusing, but let's start from the premise that colleagues work well).

  

Could there be some kind of error when working in this way on projects of several dozen files?

No error. At most compilation times will grow if your headers are very large and numerous but you will not find errors if your inclusion guards are correct.

    
answered by 23.04.2018 в 08:28
2
  

but really today it is difficult to justify its existence in C ++.

Nothing farther from reality. C ++ is a very complicated language to interpret since practically everything depends on the context (and for the record that I wish I could eliminate the headers).

Example 1:

namespace A
{
  namespace B
  {
    int func(int var)
    {
      return var + otraFunc();
    }
  }
}

Where would you say you should find otrafunc ?

  • In A :: B
  • In A
  • In the global namespace
  • In an anonymous namespace previously declared

Example 2:

a b(c);

What is this?

  • The declaration of a function
  • The declaration of a variable
  

Could there be some kind of error when working in this way on projects of several dozen files?

As far as you are concerned, you may encounter several problems when using headers exclusively:

Compile time

During the compilation phase, either with cmake , nmake , [loquequieras]make , etc. An implementation file is only compiled if any of its dependencies (header files) has undergone changes.

Under this premise, if you do not separate between header and implementation, any change in the implementation will modify the header and, consequently, any file that includes your header will have to be recompiled ... in large projects this can be translated into some another extra compile time.

Visibility

In C ++, unlike some more modern languages, there is not, for the moment, the concept of library or project. This implies that there is no visibility internal or similar, whose role is that an item is public only within its library or assembly.

Separating the code in header and implementation is easy to manage this feature making only the implementation files load the internal headers. And you could even go further and eliminate internal headers when deploying your solution, so that nobody has access to those classes except your own implementation.

Managing this unused feature, as you say, headers, is impossible, since the classes will end up being public.

Isolation

If all the code travels in the headers and you develop an application, it is better that it will not be extensible through plugins ... they will need to know, at least, the public interface of your application.

Normally this public interface is reduced to a series of headers without any code ... but with your design those headers will also incorporate the source code below and, by extension, the source code of all the classes from which depend on that interface. That exposes (want or not) your own work in view of others and creates a confusing access interface ... it is assumed that the interfaces should not contain any code and this would not be your case.

This would also be applicable in the case that you program a DLL ... along with the binaries you should include all the source code simply to allow the linking.

Cross dependencies

If you do not separate implementation headers, forget about those architectures that imply, in one way or another, cross-dependencies.

struct Padre
{
  std::vector<Hija*> hijas;

  ~Padre()
  { std::for_each(hijas.begin(),hijas.end(),std::default_delete<Hija>()); }
};

struct Hija
{
  Padre* padre;

  Hija(Padre* padre)
    : padre(padre)
  {
    padre->hijas.push_back(this);
  }
};
    
answered by 23.04.2018 в 08:05