Why different source file structure in new Projucer-generated GUI App and Audio App?


#1

Hi,

this may be a newbie-questions, but I didn’t find any answers to this by googling.

After using the Audio-Part of Juce for a Command Line Tool, I’m now just starting to learn GUI-Programming. With that, I noticed that when creating a fresh GUI Application with the Projucer, it comes with a Main.cpp, a MainComponent.h and a MainComponent.cpp file. That’s a structure I’m familiar with. However, when creating a fresh Audio Application it just has a Main.cpp and a MainComponent.cpp, the mainContentComponent Class Declaration and implementation is done completely in this one single .cpp file instead of splitting it into .h and .cpp files. As I was always used to split every C++ class I programmed until now into a .h and .cpp file I wonder what’s the reason for doing it this way in the Audio Application template?


#2

No one? I thought this would be easy to answer by experienced JUCE users and was somehow sure that there is a good reason for this difference. So it would be great to know if there is any reason for this difference or not before starting to program as I’m used to (with header and .cpp source file) and noticing what’s probably wrong with this approach after I’ve spent several hours of work :smiley:


#3

Well, the header/cpp distinction only really exists for legacy reasons involving the C preprocessor - no modern languages use a format like that, and if C++ was being designed today, I very much doubt the C++ committee would choose anything like it!

Modern C++ tends to favour header-only code where possible because it means you can add a class with 1 file instead of 2, much less code, less duplication, it doesn’t require anything to be added to a makefile/project to compile the cpp, and templated classes need to be declared in the header anyway.

And certainly if you have a local class, a small class, or a class that’s used in only one place in your codebase, it’s just a waste of time and space to have two files for it.

Counter arguments are that the cpp hides implementation details; can reduce compile time (but that’s not always true! Too many cpps can drastically slow down compile time); makes it easier to skim-read what a (large) class does.

The only killer argument for splitting files IMHO is where you have a class which is included in many places, but whose implementation is complex or requires including other headers, and you don’t want every dependent class to get cluttered up by including them indirectly. So putting the complex stuff in the cpp using a pimpl pattern reduces the burden on the places where you class is used. This is a common library pattern, but in apps I’d recommend keeping classes small and inline where possible.


#4

Thank you for your answer, that makes things a bit more clear.

I think I understand your explanation and the benefits of writing header-only code. But back to my original question, the projucer only puts a MainComponent.cpp into the new Audio Project, not a MainComponent.h (which is the way you described it if I got you right?). If it was a header file that would be included in Main.cpp, I would perfectly understand how it works - I think the preprocessor “copies” the content of the header to the location the #include-statement is placed and then the compiler sees everything as if it would have been written to one single big source file. But this way I’m really confused about how the Main.cpp or the compiler “knows” about the existence of MainComponent.cpp and knows that it finds

Component* createMainContentComponent();

in MainComponent.cpp. Could you give me a hint about what happens here? :wink:


#5

It’s just a function… all functions are resolved by the linker at link-time. It doesn’t matter where in your program you actually declare them.


#6

Hahaha, okay… I think I always had the wrong assumption that the linker finds the corresponding source file including a function by having a header file with the same filename except for the file extension. But that seems to my misunderstanding. Great, now I understand everything!