About headers in C ++

2

Some doubts arise specifically about creating headers:

  • If I create a test.h file, and another test.cpp, as the C ++ compiler does to relate the test.cpp file to the test.h file, that is, what are the criteria used? What prevents the settings for test.h in test.cpp from being replaced by others?
  • (Completion of the previous question) If we create a test.h file and implement it in a different file name, say, test.cpp, the program compiles. How to explain this?
  • Why does not the following code compile? I get an 'undefined reference to cube' error.
  • /* teste.h */
    #ifndef TESTE
    #define TESTE
    
    inline double cubo(double a);
    
    #endif // TESTE
    
    /* Teste.cpp: implementação de Teste.h.*/
    #include "teste.h"
    
    double cubo(double a)
    {
        return a * a * a;
    }
    
    /* Principal.cpp */
    #include <iostream>
    #include "teste.h"
    
    int main()
    {
        std::cout << cubo(2.0) << std::endl;
    }
    
  • When implementing a inline function in a .cpp file, does it make any difference to remove the inline qualifier from the function definition, leaving only the statement?
  • I read in several places that defining inline functions in header files helps prevent "multiple function definitions". Could you explain how these "multiple definitions can occur"?
  • I'm using Qt Creator on Linux (Kubuntu 16.04). The compiler is gcc (g ++).

        
    asked by anonymous 03.08.2017 / 18:21

    2 answers

    0
      

    If I create a test.h file, and another test.cpp, as the C ++ compiler does to relate the test.cpp file to the test.h file, that is, what are the criteria used? What prevents the settings for test.h in test.cpp from being overridden by others?

    You need to know the following things:

    1) include puts the code of a header in the same place where the include was. I mean, header is not source code to compile, it just contains codes that will be embedded in real source codes (those are indeed compiled).

    This means that the test.cpp, due to include, does the same as the following (with the difference that the include takes away your need to copy the entire header to the source code).

    /* Teste.cpp: implementação de Teste.h.*/
    
    // Começa o #include "teste.h"
    /* teste.h */
    #ifndef TESTE
    #define TESTE
    
    inline double cubo(double a);
    
    #endif // TESTE
    // Termina o #include "teste.h"
    
    double cubo( double a )
    {
        return a * a * a;
    }
    

    2) Define something is to create this thing so that it can be used in the .cpp file where it was defined. It was what you did in the test.cpp, you defined the cube function.

    3) To declare something is to warn that it exists (even if in another file) and that it can be used. That's what you did in the test.h, you declared the cube function. Therefore, where you include the test.h you will be advising that you can from then on in the source file use the function.

    When you do #include "teste.h" in the test.cpp, you are putting the declaration of something that soon is already defined there, that is, it is unnecessary in the test.cpp. The include is only needed if the header declares something that will not be defined or declared in the same file, which is the case of main.cpp.

    4) When compiling the source codes, there is the linking process. Each source file gives rise to an object file with the symbols used in the code. These symbols of the object files are connected to each other in such a way that the definition in one source code can be used in another where you have the declaration.

    It means that the cube function has the cube symbol existing in main.cpp (where it is declared and used) and test.cpp (where it is defined and could be used, but it is not), there the liner allows main. cpp has access to the setting in test.cpp so that you can use the function. Without the linkage, main.cpp does not have access to the cube function defined in test.cpp.

    Note: There are no overrides for definitions. If the linker finds two, the calls are ambiguous and therefore a semantic compilation error occurs because the linker will not know how to differentiate the definition that should be used.

      

    (Completion of the previous question) If we create a test.h file and implement it in a different file name, say, test.cpp, the program compiles. How to explain this?

    If declared in the test.cpp, the test.cpp can use the function as well. But if you set it there while it is set to test.cpp and enable the linking of both files, the settings conflict, cause ambiguity, and generate misleading.

      

    Why does not the following code compile? I get an 'undefined reference to cube' error.

    If main.cpp uses a function but it is not defined, then this error appears. To find the definition, the test.cpp (which has the definition) has to be compiled to generate object code. It means that you are not compiling the test.cpp, so it is not being linked. You need to compile the two.

      

    When implementing an inline function in a .cpp file, does it make any difference to remove the inline qualifier from the function definition, leaving only the statement?

    Must be set with inline. However this effect also depends on the compilation options, which can disable inline or even release inline for functions not defined so if the compiler deems beneficial. If I'm not mistaken, the default is called a function from one file to another not generating inline code.

      

    I read in several places that defining inline functions in header files helps prevent "multiple function definitions". Could you explain how these "multiple definitions can occur"?

    For example.

    double Double( int x , double *p ){
        return *p = (double)x ;
    }
    
    double Double( int z , double *p ){
        *p = 2.0*z ;
        return *p ;
    }
    

    This is multiple definition. Two functions of the same signature (name and parameters Double(int,double*) ), even though they are different functions, generate ambiguity. It does not have a problem to define in different files (each file uses its function) unless the symbol is declared somewhere (since there is no known where to link that one, there it gives the error that I discussed previously).

    I hope I have clarified. Otherwise, let me know.

        
    03.08.2017 / 21:59
    2

    Below are the specific questions, but I understand that the questions are actually about the error generated by inline .

    Whenever you use inline the implementation code of the function must be on the same compilation drive, it can not be anywhere else. Do not just have the function signature . This is different. Since the function code will probably have to be used in your new code and will not be called, the source must be available right there. So in this case the correct one is to have the header like this:

    #ifndef TESTE
    #define TESTE
    
    double cubo(double a) {
        return a * a * a;
    }
    
    #endif // TESTE
    

    See running Coding Ground . Also I put it in GitHub for future reference .

    Documentation on inline .

      

    If I create a test.h file, and another test.cpp, as the C ++ compiler does to relate the test.cpp file to the test.h file, that is, what are the criteria used? What prevents the settings for test.h in test.cpp from being overridden by others?

    Nothing, who does this is code, the compiler only does what is determined by the code.

      

    (Completion of the previous question) If we create a test.h file and implement it in a different file name, say, test.cpp, the program compiles. How to explain this?

    Exactly what is above, there are no implicit links, the code says what it should link, so it works with names you like. Of course the content needs to be adequate.

      

    Why does not the following code compile? I get an 'undefined reference to cube' error.

    This is a linking error, he found all the code but did not find it the binary needed to create the executable. It depends on how you are compiling, it may just be that you have not added the .cpp , you may need to indicate where the previously compiled code is. This can be a problem in configuring the IDE project.

      

    When implementing an inline function in a .cpp file, does it make any difference to remove the inline qualifier from the function definition, leaving only the statement?

    Overall it makes no difference because the compiler will inline if it wants. But for the purposes of having the code can make a difference.

    If you say it's inline you have to have an executable code for that function on that drive, and you probably have not put it there. When you do not use it, it may be resolved elsewhere.

      

    I read in several places that defining inline functions in header files helps prevent "multiple function definitions". Could you explain how these "multiple definitions can occur"?

    The question is a bit broad, but roughly the heading is a centralizer, there is the correct place to put inline functions since it will be used wherever you need it. If you start spreading them through several files, who guarantees that they are all the same?

        
    03.08.2017 / 18:52