Why do we need a header file? And why multiple ".cpp" files for every project?

No, you definitely shouldn’t!

Example code is written to show you how a particular class or concept works. It is not written to show you how to structure a real-world project.

It’s also generally small, without the need to worry about scaling it up as the project grows.

In fact, most of our examples are now arranged as single-file PIPs, and a PIP is definitely not the structure you’d want to choose for building a real production app!

*cough* /extras/projucer/ *cough*

Can we keep this productive, please?
You were talking about examples…
Also the Projucer is under constant development as well, many things would be done differently today, so it is still true: read everything, but make your own choices.

You are using an IDE, right? Then it doesn’t matter that much for navigation in how many files your code is spread because you can just use the features to jump into the declarations and definitions.

1 Like

Right… and if you’re writing an app that has a similar complexity and scale to the projucer, then yes: the projucer is probably a pretty decent example of how to structure it.

But if you’re building something entirely different - like the OP is - then the patterns we used in the Projucer aren’t necessarily appropriate.

I’m involved with many real-world projects, and they’re all structured a bit differently according to their needs. That’s why it’s important to flag for anyone who’s struggling to learn how to do it that there’s no “one-size-fits-all” answer. And looking at how other software is done - even if it’s very good - doesn’t necessarily help much unless it’s very similar to what you’re trying to do.

Hi jules. Can I ask why you prefer the header only approach?

Well, you could ask why every modern language designed after C++ chose to declare classes as single blocks of code.

The whole header/cpp thing wasn’t designed to make life easier or better for the programmers, it was to make it feasible for compilers to parse it, back in the days when they were working in constrained environments. IMHO it’s one of the worst legacies of C++'s history.

Personally I don’t like superfluous repetition, and if your classes are quite small (as they should be!) then I find it neater for them to just be a single lump of code.

Obviously in bigger projects there are lots of cases where you need to hide things in a cpp or organise larger classes that way, or just fix order-of-declaration trouble, so it has its place.

1 Like

Funny, guess it comes down to preference sometimes. I always liked the separation, probably from having grown up with it, and always found headed files a clean view of what functionality was offered without it being spoilt by implementation. Took me a long time to get used to java, but I guess I did eventually. When moving back to c++ I found myself much happier being able to go back to cop/h.

1 Like

Having learned OO in Smalltalk, when C didn’t have the ++ yet, there was a nice browser, that showed Classes and all their methods, including inherited ones. That was nice to get an overview of what an object is capable of very quickly. I think ObjectiveC does it this way.

I also like to look at headers (or doxygen pages), and only go into the implementation, if I need to know details. But it is just a matter of using your IDE properly.

(ok, it was 98, so C++ was invented, but not as present as it is now. Just 2 years later nobody seemed to do pure C any longer…)

my preference these days tends to be to use header-only classes where possible, and to keep the number of CPPs down to the correct number

I also prefer to use low cpp number but for newbie reasons: I started with cpp + h for each class/module but using headers made me implement changes faster, specially now that I’m in the trial & error stage and still learning.

OP, I had the same reasoning when I started some months ago on C++ and JUCE, and you will end up realising that you prefer to split code in various files once you start changing your stuff. I basically makes it much easier to deal with, and lets you just go straight to the code you need to change instead of looking into thousands of lines.

Regarding on other’s code, I also agree on not taking other’s synth projects as models but as learning stuff. I’ve learned tons of how to do things just from reading other’s code and realising how they handle stuff, it gives a bigger picture and an insight on how things can be done in many different ways but that doesn’t mean it’s the best way (and afaik there are only “better than”, not “the best way” to do X). You can even look into JUCE examples and see how they do the different things in many ways, for instance all the oscillator stuff

I will give you my answer to your question, based on my own experiences and opinions as a programmer and software analyst.

I can understand why you have this temptation to have fewer files. I think it is because you do not yet appreciate object oriented programming (OOP). OOP can be a little difficult to understand or appreciate in the beginning. But when you create larger and larger projects, you will inevitably begin to realise that code quickly becomes like spaghetti. Therefore, programmers tend to gravitate towards various ways of organising their code. Its just like any other complicated task that you might perform: organisation can make it easier to manage the complexity.

The current project I’m working on, for example, has almost 300 classes (not including JUCE or any other external libraries), so that’s almost 600 files. If I was to put all of that into one file, it would be ridiculous. I would constantly be lost in all of that code.

Even a file that has 400 lines can start to become a nuisance for me. So I try to keep the files much smaller. I organise my code by grouping any functions that perform a similar purpose, into one file.

3 Likes

Having only a single file is like glueing all the books on your bookshelf together so you only have to pick up one book to read. You’ll get the right “book” but finding your place in it and trying to read it will be… difficult.

12 Likes

Great metaphor. Reminds me of how frustrating it can be when the pages of certain magazines get stuck together over time :sweat:

1 Like

To a certain extent, this comes down to style and personal preference.

Historically, from the days of “C”, header files are for declaring and “.c”, or now, “.cpp”, are for defining and implementing.

You might have more than one file so as to divide up the project in a way that makes it easier to keep track of what is going on. And, also, make it easier to find errors.

And finding errors is an important part of programming! Remember, until a program is “finished”, you will compile it a great number of times with errors. So, a large factor in the completion of any program is finding and fixing errors quickly. The multiple file approach helps with this by the “divide and conquer” strategy.

Can you put everything in one file? Yes. There are no C++ police to knock down the door.

But I urge you as you develop your programming talents to, at least, try the multiple file approach and see, if like most people, you find it easier to keep track of everything.

By the way, the “header only class” mentioned here is an even more succinct style, you may want to investigate. It eliminates the corresponding “.cpp” file, and makes code more readable IMHO for compact classes.

I admit I haven’t read this whole thread, which is quite long, so I apologise in advance if this point has been made already…

In addition to being easier to maintain and work with, splitting code into separate classes makes it portable and reusable. Say you designed an oscillator for your synth, and went to the trouble of encapsulating it in a standalone class. On your next plugin you can easily drop that single file (or two files, if you have a .h and .cpp) into your project, add a couple of lines of configuration and BAM, you have an oscillator up and running.

The benefits of this approach are very obvious when you are working with someone else’s code. You mentioned the VanillaJuce project. Let’s say you want to reuse the Oscillator from VanillaJuce. The plugin’s developer has made it easy for you to do so by encapsulating all of the logic for the oscillator in one class (two files): SynthOscillator. If the plugin’s entire logic was jumbled together in one monolithic file it would be significantly more challenging to locate the parts that related to the oscillator, understand how it relates to the rest of the code, and reimplement it in a different project.

It’s slightly annoying that examples are not in the same CPP/H format as when you create a ‘New project’. It would have been helpful for JUCE beginners if they were.
Just my 2p’s worth. :slight_smile:

1 Like

By the way, the “header only class” mentioned here is an even more succinct style, you may want to investigate. It eliminates the corresponding “.cpp” file, and makes code more readable IMHO for compact classes.

I really like the sound of that. I would like to keep my file count down but I do get the idea of separating things out. Thanks for the suggestion. I see no need to separate the class declarations from the function definitions for my personal use. So that is what I will likely do.

I understand the general principle much better from this thread.

Another interesting perspective is the one here which has been suggested by users like @jnicol in terms of reusability of classes:
http://www.ntu.edu.sg/home/ehchua/programming/cpp/cp3_OOP.html

For better software engineering, it is recommended that the class declaration and implementation be kept in 2 separate files: declaration is a header file " .h "; while implementation in a " .cpp ". This is known as separating the public interface (header declaration) and the implementation. Interface is defined by the designer, implementation can be supplied by others. While the interface is fixed, different vendors can provide different implementations. Furthermore, only the header files are exposed to the users, the implementation can be provided in an object file " .o " (or in a library). The source code needs not given to the users.

This isn’t really relevant as a small time user, but I can imagine how that would be practical and ideal from a corporate or big fish perspective. And it makes sense for how it allows you to “piece together” a project from multiple pre-defined classes.

Thanks everyone for the clarification. I won’t glue all the pages of the book together. At least not on purpose.

I generally have most of my classes defined as header only (.h) files. Makes things easier to manage - I personally find having to write the declaration and definition separately in two different files cumbersome. Sometimes however it makes sense to do it that way, and sometimes its necessary to avoid cyclical include issues or when the implementation of a class needs to be hidden.

You must also enjoy really long compile times lol

2 Likes

Actually I originally started doing it after a comment from Jules on a similar question I put on the forum a few years ago.