2

The common practice in C++ is to separate declarations in .h (or .hpp) and implementation into .cpp.

I know about two main reasons ( maybe there are others ):

  1. Compilations speed ( you do not have to recomplie everything when you change just one file, you can link it by make from pre-compiled .o files )
  2. Forward declarations are sometimes necessary ( when implementation of class A depends on class B and implementation of class B on class A ) ... but I don't have this problem so often and usulaly I can solve it.

In case of object oriented programming it looks like this:

QuadraticFunction.h:

class QuadraticFunc{
    public:
    double a,b,c;
    double eval ( double x );
    double solve( double y, double &x1, double &x2 );
};

QuadraticFunction.cpp:

#include <math.h>
#include "QuadraticFunc.h"

double QuadraticFunc::eval ( double x ){ return c + x * (b + x * a ); };

double QuadraticFunc::solve( double y, double &x1, double &x2 ){ 
    double c_ = c - y;
    double D2 = b * b - 4 * a * c_;
    if( D2 > 0 ){
        double D = sqrt( D2 );
        double frac = 0.5/a;
        x1 = (-b-D)*frac;
        x2 = (-b+D)*frac;
    }else{  x1 = NAN; x2 = NAN; }
};

main.cpp :

#include <math.h>
#include <stdio.h>

#include "QuadraticFunc.h"

QuadraticFunc * myFunc;

int main( int argc, char* args[] ){

    myFunc = new QuadraticFunc();
    myFunc->a = 1.0d; myFunc->b = -1.0d; myFunc->c = -1.0d;

    double x1,x2;
    myFunc->solve( 10.0d, x1, x2 );
    printf( "soulution %20.10f %20.10f \n", x1, x2 );

    double y1,y2;
    y1 = myFunc->eval( x1 ); 
    y2 = myFunc->eval( x2 );
    printf( "check     %20.10f %20.10f \n", y1, y2 );

    delete myFunc;
}

then compile it with makefile like this:

FLAGS  = -std=c++11 -Og -g -w
SRCS   = QuadraticFunc.cpp main.cpp
OBJS   = $(subst .cpp,.o,$(SRCS))

all: $(OBJS)
    g++ $(OBJS) $(LFLAGS) -o program.x

main.o: main.cpp QuadraticFunc.h
    g++ $(LFLAGS) -c main.cpp

QuadraticFunc.o: QuadraticFunc.cpp QuadraticFunc.h
    g++ $(LFLAGS) -c QuadraticFunc.cpp

clean:
    rm -f *.o *.x

However, I find it often very inconvenient

especially, when you change code a lot ( e.g. in initial phase of development when you are not yet sure about overall structure of the whole project ).

  1. You have to go back-and-forth all the time between .cpp and .h part of code when doing significant changes to the class structure.
  2. You have twice as much files in the editor and in project folder which is confusing.
  3. You have to write some informations ( like function headers or QuadraticFunc:: ) twice, where you can do many typos and inconsistencies so the compiler complains all the time ( I do such mistakes very often )
  4. Every-time you add / remove / rename some class you have to edit Makefile, where you do a lot of other mistakes which are hard to track from the compiler output ( e.g. I often forgot to write Makefile so that the code recompiles every dependency which I edit )

From this point of view I like much more how Java works. For this reason I was writing my C++ programs simply by putting all the code (including implementation) inside .h. Like this:

#include <math.h>
class QuadraticFunc{
    public:
    double a,b,c;
    double eval ( double x ){ return c + x * (b + x * a ); }
    double solve( double y, double &x1, double &x2 ){ 
        double c_ = c - y;
        double D2 = b * b - 4 * a * c_;
        if( D2 > 0 ){
            double D = sqrt( D2 );
            double frac = 0.5/a;
            x1 = (-b-D)*frac;
            x2 = (-b+D)*frac;
        }else{  x1 = NAN; x2 = NAN; }
    };
};

with universal default makefile like this:

FLAGS  = -std=c++11 -Og -g -w

all : $(OBJS)
    g++ main.cpp $(LFLAGS) -w -o program.x

( main.cpp remains the same )

However, now when I'm starting to write more complex programs, the compile time starts to be quite long when I have to recompile everything all the time.

Is there any way how to use advantages of make ( faster compile time ) and still organize program structure in the Java-like way ( everything in class body instead of separate .h and .cpp ) which I find much more convenient ?

Prokop Hapala
  • 2,424
  • 2
  • 30
  • 59
  • AFAIK, no, and this will make a very big problem: circular dependencies. – Danh Dec 28 '15 at 08:38
  • 1
    Unrelated, but there is no reason to dynamically allocate a `QuadraticFunc` object in `main`. Just use an automatic variable. – juanchopanza Dec 28 '15 at 08:46

4 Answers4

6

However, now when I'm starting to write more complex programs, the compile time starts to be quite long when I have to recompile everything all the time.

One of the best points in separating header and the class file is that you don't have to compile everything.

When you have class1.h, class1.cpp, class2.h, class2.cpp, ... ,classN.h and classN.cpp, those headers are only included in the compiled objects of each class. So if your function's logic changes in class2 but your header doesn't, you'll only have to compile class2 into object file. Then you'll do the linking for all object files which produces your actual executable. Linking is FAST.

If you are building large and complex programs and find that editing the headers is the problem, consider DESIGNING your application before writing it.

Simo Erkinheimo
  • 1,347
  • 9
  • 17
  • yes, exactly, this is the original motivation of the question – Prokop Hapala Dec 28 '15 at 08:47
  • What comes to typos and jumping between header and class file, a good IDE is what you need. Some IDEs even notice what you have and haven't edited and builds only what is neccessary. When the IDE handles building, you might not even ever need to see the makefile. – Simo Erkinheimo Dec 28 '15 at 10:25
  • that is probably true ( it is not good to compare Java where I use Netbeans to C/C++ where I use gedit and gcc ). But still the fact that I do not have to use any heavy IDE with C/C++ and that I have control about what is happening under the hut I consider as one advantage of C/C++ programming. – Prokop Hapala Dec 28 '15 at 10:31
  • Usually using an IDE will pay back the time you lose when you're not using one even if the IDE was a bit heavy (compared to gedit). Not sure about its functionalities, but http://codelite.org/ is said to be one of the lightest. – Simo Erkinheimo Dec 28 '15 at 10:54
1

Short answer: no.

Long answer: Still no.

Either you put all your code in a header file, or you use two files, where the header is included and the source file compiled on its own.

I personally have no problem with using two files. Most editors support a "two file view" - and most of them also support "jump to definition of ".

Putting all functions inside the class declaration also has another side-effect, and that is that all functions are marked inline, which can lead to the function being produced multiple times in the output binaries if the same header is included in several source files.

Although the compile time, in my experience, is not a consequence of parsing, but of the code-generation part of the compilation - which typically is the .cpp file - so if you include several large headers most likely won't matter that much.

Of course use make [or something similar] with properly defined dependencies to build your project.

Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
1

C++ is C++ and Java is Java. Splitting your source code in .h- und .cpp files is part of C++'s language concept. If you don't like it you shouldn't use it.

Putting everything in one header-file is practially the same as including the .cpp file (which works but is highly inappropriate). You should not do this when:

  • writing standard classes, functions,...
  • using the code section multiple times in bigger programs (leads to redefinition error when you include everything in main.cpp otherwise)
  • you want to outsource part of your program in a static/dynamic library. Pretty much every available library created works that way.

Examples: WindowsAPI (COM!!), SFML, Boost (partly) (and a lot more)

You could do this when:

  • the code does very simple things, e.g. Bit-shift operation (making color codes), string analysis,...

Examples: Boost (partly)

You must do this when:

  • Creating template classes or functions as they are generated at compiling runtime. This is one of the major and most discussed downsides on the .h/.ccp-concept, so you are not the first one to wonder about it.

Examples: STL (C++ standard template library)

BeschBesch
  • 373
  • 2
  • 11
  • oh, templates would not work with `.cpp` and `.h` separated ? That is pretty bad ... I do a lot of low-level performence intensive math where I use templates and inline functions. Actually, that is one of the main reasons why Java does not satisfies me. – Prokop Hapala Dec 28 '15 at 09:22
  • See the [question](http://stackoverflow.com/questions/1724036/splitting-templated-c-classes-into-hpp-cpp-files-is-it-possible) for further information – BeschBesch Dec 28 '15 at 09:25
  • ad **redefinition error** ... I include everything only in `main.cpp` so there cannot be any redeclaration error I think – Prokop Hapala Dec 28 '15 at 09:26
  • `Putting everything in one header-file is practially the same as including the .cpp file` ... yes, exacactly. Maybe I should have formulate it as `including .cpp file` in original question to avoid some confusion. – Prokop Hapala Dec 28 '15 at 09:30
  • Example: You define baseclass in a.h (implementation, static variables, may some global vars), inlcude it in b.h and c.h because you need it there and then you include b.h and c.h in main.pp. You would the redefine the baseclass and this could lead to compiler errors. @Second: No, don't do that, you **never** include .cpp-files. #include is only used for .h-files. – BeschBesch Dec 28 '15 at 09:31
  • If I alwas compile just main.cpp I do not have to include a.h into c.h and b.h. I have to only to make sure that a.h is included in main.cpp before including b.h and c.h ... but I understand what you mean. – Prokop Hapala Dec 28 '15 at 09:34
0

First of all you have to write implementation and definition in seperated file because of readebility. İt is possible to put them into same file , but it is not readable . When writing code, write for the next contributor who will need to understand your code. That is important because the next one may be you :) Second issue is makefile . Make is to make easier compilation process not faster . So if you make change in any of your file, you don't need to make change ant make files. Thanks of make , you dont need to compile your file in order again and again.write the files once , use every time. But if you add new code file which effect compilation process ,yes you have to make change in makefile. You can more information about readability,writing definition and implementation in seperate files and the all other style issue in google c++ style guide and about makefile in gnu make manuel.

O.AYYILDIZ
  • 86
  • 8