C++ main() in a large OOP project - c++

This may be a short & simple question, but I've never found a satisfying answer to it:
What code does the main() function usually consist of in a large C++ project? Would it be an incorrect assumption to think that it is usually just initializing a (wrapping) class object and calling a function inside of it to set things off?
Why is main() not a method in the first place? Is it to preserve backwards-compatibility with C?

In my code, it's basically a constructor call, possibly a method call, and some exception handling. This is the main for own of my projects (headers and comments omitted, and formatting messed up by SO, as usual):
int main( int argc, char * argv[] ) {
int result = 0;
try {
CLIHandler ch( argc, argv );
result = ch.ExecCommand();
}
catch( const Exception & ex ) {
result = ExceptionHandler::HandleMyError( ex );
}
catch( const std::exception & ex ) {
result = ExceptionHandler::HandleOtherError( ex );
}
catch( ... ) {
result = ExceptionHandler::HandleUnknownError();
}
return result;
}

Mine usually do
Command-line parsing
Initialization of top-level objects
Exception handling
entering main 'exec' loop
As I understand it, int main(int argc, char *argv[]) is essentially a convention due to the C heritage. Never struck me as odd, but rather as useful. C++ extends C after all ... (and yes there are fine difference but that wasn't the question here).

Yes, the reason is backward compatibility. main is the only entry point allowed in a C program producing executables, and therefore in a C++ program.
As for what to do in a C++ main, it depends. In general, I used to:
perform global initialization (e.g. of the logging subsystem)
parse command line arguments and define a proper class containing them
allocate an application object, setting it up etc.
run the application object (in my case, an infinite loop method. GUI programming)
do finalization after the object has completed its task.
oh and I forgot the most important part of an application
show the splashscreen

The short answer: it depends. It may well create a few local objects that are needed for the duration of the program, configure them, tell them about each other and call a long running method on one of them.
A program needs an entry point. If main had to be a method on an object, what class type should it be?
With main as a global entry point it can choose what to set up.

My main() function often constructs various top-level objects, giving them references to one another. This helps minimize coupling, keeping the exact relationships between the different top-level objects confined to the main.
Often those top-level objects have distinct life cycles, with init(), stop(), and start() methods. The main() function manages getting the objects into the desired running state, waits for whatever indicates it is time to shut down, and then shutting everything down in a controlled fashion. Again, this helps keep things properly decoupled, and keeps top-level life cycle management in one easily understood place. I see this pattern a lot in reactive systems, especially those with a lot of threads.

You can use a static class member function in place of main with the MSVC++ compiler by choosing the entry point in the project settings, under the advanced linker options.
It really depends on your project as to what you want to place in there... if it is small you may as well put message loops, initialization and shutdown code in there. In larger projects you will have to move these into their own classes/functions or less have a monolithic entry point function.

Not all C++ applications are OOP and either way all code requires some entry point to start from.
When I'm writing OOP code, my main() tends to include an object instantiation, maybe proceeded by some user input. I do it this way because I feel that the 'work' is meant to be done within an object, otherwise the code isn't written in the 'spirit' of OOP.

I usually use main for reading in the command line, initializing global variables, and then calling the appropriate functions/methods.

Really large projects tend not comprise only a single program. Hence there will be several executables each with their own main. In passing, it's quite common for these executables to communicate asynchronously via queues.
Yes each main does tend to be very small, initialising a framework or whatever.
Do you mean why is main() a function rather than a method of class? Well, what class would it be a method of? I think it's mostly C++'s heritage from C, but ... everything got to start somewhere :-)

Related

Override the call to main()?

I'm working on a project where we have several executables that share several object files. We want to add logging to all of the executables, and have a library for doing so.
However, it seems clumsy to go to the main() function of every executable file and add in the same boiler-plate function call to start the logging. It means we write the same thing over again, and loose out on maintainability and DRY ("don't repeat yourself"). It would be nice if we could systematically ensure that logging started before the main function gets called.
It occurred to me there are functions in libc++ that make the call to main, and it may be possible to override them. However, I don't know what they are and imagine this could break things if we're not careful. Does anyone know how this would be done? Or, if that's too over-the-top, any other suggestions on how to proceed?
We're using C++11 with g++ 4.8 if it makes any difference.
You do not need to do this by modifying main().
You should instead create a class at global scope in a shared object library. The constructor of this class will perform the "initialisation" you want to do, before main() runs, and its destructor will run after main().
The issue you need to deal with is that the order of this initialisation and destruction is not guaranteed to be deterministic with regards to any other global-scope objects. All of this could go in one .cpp compilation unit.
class LoggingManager // you can make this a singleton but not necessary
{
public:
LoggingManager();
~LoggingManager();
};
LoggingManager::LoggingManager()
{
// your initialisation code goes here
}
LoggingManager::~LoggingManager()
{
// your clean-up code goes here. It should not throw
}
LoggingManager loggingManagerStaticInstance;
Note that there is a small danger of the "static initialization" issue which means in reality your loggingManagerStaticInstance might not be loaded until your compilation unit is first accessed.
In reality it doesn't matter if this is after main() as long as the initialisation happens before it is first needed (a bit like a singleton) but it means your compilation unit might need to contain something that is guaranteed to get pulled in.
If you want to "stick" to gnu or similar they provide __attribute__(constructor) which might resolve it although there is an easier way of having some dummy extern int implemented or dummy function that returns an int that gets called from within whatever header you do actually use to implement logging.

Is it bad practice if I have to organise Compile Sources

I am working on a C++ project in Xcode, and one of my .cpp files instantiates some variables. Another .cpp file in the application uses these variables to instantiate another object and needs them to be instantiated to not throw a null-pointer exception. My solution so far was simply to drag-drop (XCode simplicity) the first file over the second one in the build-phase order. It works fine now, but I have a feeling that it is not the optimal solution, and that there is something fundamentally wrong with my code if I need to organise the compile order manually for the application to run properly.
Should I never instantiate something outside of functions, or what is the golden rule? Thanks.
EDIT: An example as requested.
The problem lies in a Observer/Event system.
In a source-file I do this:
Trigger* mainMenu_init = new Trigger(std::vector<Event*> {
// Event(s):
event_gameInit,
}, [](Event* e) {
// Action(s):
std::cout << "Hello World" << std::endl;
});
In the trigger's constructor the Event is asked to add is as an observer:
for(Event* event : events)
event->addObserver(this);
BUT, the events are just external pointers, so if they are not initialised (which they are in another source-file) this initialisation will fail. So what I found was that if I do not organise the compilation-phase myself, random triggers will not work while other will, depending on if they are built before or after the Event.cpp file.
I assume you are talking about non-trivial initialization of global variables (or of static variables), such as (at the top level of a file):
MyObject *myPtrObject = new MyObject(42, "blah");
MyObject myOtherObject;
("trivial" initialization is, roughly speaking, when there is no constructor involved and everything just involves constants; so if you initialize a pointer to zero, it will be zero before any code is actually invoked)
The order of initialization between different source files is NOT GUARANTEED in C++. It happens to depend on the order of the files with Apple's current system, but THAT MIGHT CHANGE.
So yes, there is something fundamentally wrong.
Golden Rules
IMPORTANT: In the initialization of a global object, don't use any other global objects from different source files.
Don't overuse global variables. They have numerous disadvantages from a software design point of view.
Keep initialization of global objects simple. That will make it easier to stick to the first rule.
Not knowing anything about your program, it's of course hard to give more concrete design advice.

How to pass data to glutTimerFunc?

#include <gl/freeglut.h>
void Keyboard(int value){
glutTimerFunc(33,Keyboard,0);
}
int main(int argc, char **argv){
glutTimerFunc(33,Keyboard);
}
Is there any way to pass data from the main function to the keyboard function without having to use global variables? It seems like the function glutTimerFunc only allows functions with the signature (int value) which seems very restrictive.
so is there another way to get the data into another funcion without having them to be global?
Like other people already suggested: Don't use GLUT. GLUT never was meant to be the foundation of serious application. It's a small framework meant for small OpenGL tech demos. The problem you're running into is that C and C++ lack a concept called "closures", or sometimes also called "delegates". Other languages have them and in fact when you use the GLUT bindings in those languages you don't experience the problem.
Since C/C++'s lack of closures is so prominent a small library (that does crazy but genius things internally) has been written, that allows it, to create closures in C. It's called ffcall, unfortunately seems to be unmaintained, but is in use by projects as the GNU Common Lisp and Scheme compilers.
I wrote about using ffcall already in the StackOverflow answers https://stackoverflow.com/a/8375672/524368 and https://stackoverflow.com/a/10207698/524368
You can use a trick: pass a pointer to the object as value, after casting it to int:
i instance;
keyboard((int)&i);
If you need to call the function with the timer, consider the fact that when a function ends all the object in the stack are deallocated. So in this case you should allocate the object with new, and always have a handle to it in the case you need to deallocate it.
It's very tricky, I know. If you can switch to another library do it.

Basic C++ Design

I have a question re my C++ class design. Often I face little issues like this and I'd like some advice as to what is better accepted.
I have some class which monitors the temperature of some device over UDP. If the device receives a packet of data, it is to print "x\n" to stdout to show that it received something. Then it is to check the data in that packet and verify that the data doesn't show that the temperature of the device is too high. If it is too high, I must call some function. If it isn't, I must call some other function.
I'm not sure if I should do this:
enum temperature {TEMPERATURE_FINE, TEMPERATURE_EXCEEDED};
int main(int argc, char* argv[])
{
std::vector<std::string> args(argv+1, argv + argc);
if(!args.size())
cout << "No parameters entered.\n";
else
{
CTemperatureMonitor tempMonitor(args);
if(tempMonitor.MonitorTemperature() == TEMPERATURE_EXCEEDED)
tempMonitor.ActivateAlarm();
else
tempMonitor.DisableAlarm();
}
return 0;
}
where tempMonitor.MonitorTemperature() calls std::cout << "x\n". So std::cout << "x\n" is built into the class.
Or:
enum temperature {TEMPERATURE_FINE, TEMPERATURE_EXCEEDED};
int main(int argc, char* argv[])
{
std::vector<std::string> args(argv+1, argv + argc);
if(!args.size())
cout << "No parameters entered.\n";
else
{
CTemperatureMonitor tempMonitor(args);
temperature tempExceeded = tempMonitor.MonitorTemperature();
std::cout << "x\n";
if(tempExceeded == TEMPERATURE_EXCEEDED)
tempMonitor.ActivateAlarm();
else
tempMonitor.DisableAlarm();
}
return 0;
}
where std::cout << "x\n" is not included in the class.
The std::cout << "x\n" must occur before calling CTemperatureMonitor::ActivateAlarm() and CTemperatureMonitor::DisableAlarm().
I know this might seem really minor and simplistic, but I'm often wondering what exactly should be part of the class. Should the class be outputting to stdout? Does it make any difference whether I do one or the other? Am I being to pedantic about this?
Also, as an aside, I know global variable are considered poor practise. I use the temperature enum in both the main and the class. Should I declare it twice, once in main and once in the CTemperatureMonitor class, or once globally? Although this question seems rather specific, it would actually clear a whole lot of other things up for me.
Thanks.
First off, I'd like to point out that there are various size of projects, and that depending on the size (and criticity), the advices will actually be different. So first a rule of thumb:
The size of the "framework" that you put in place (Logger, Option Parser, etc...) should probably not exceed 10% of the total program. After this point, it's just overkill. Unless it's the goal of the exercise!
That being said, we can start have a look at your actual questions.
Also, as an aside, I know global variable are considered poor practice. I use the temperature enum in both the main and the class. Should I declare it twice, once in main and once in the CTemperatureMonitor class, or once globally?
You are actually mistaking variables and types here. temperature is a type (of enum kind).
In general, Types are used as bridges between various parts of the program, and to do so it is important that all those parts share the same definition of the type. Therefore, for types, it would be bad practice to actually declare it twice.
Furthermore, not all globals are evil. Global variables are (shared state), but global constants are fine, and usually play a role similar to types.
I know this might seem really minor and simplistic, but I'm often wondering what exactly should be part of the class. Should the class be outputting to stdout? Does it make any difference whether I do one or the other? Am I being to pedantic about this?
There are two kinds of output:
logging output, which is used to diagnose issues when they are encountered
real output, which is what the program does
Depending on programs, you might have either, both or none.
From a pedantic point of view, you would generally prefer not mix those. For example, you could perfectly send the logging to a file, or stderr when it's serious, and use stdout for the "useful" stuff.
This actually drives the design somewhat, as then you need two sinks: one for each output.
Being that you have a quite simplistic program, the easiest way might be to simply pass two different std::ostream& to your class upon construction. Or, even simpler, just have two generic functions and use the (evil) global variables.
In larger program, you would probably design a Logger class that would have various log levels and provide specific macros to register (automatically) the function name, file name and line number of the log line. You would also probably have a lightweight logging mechanism that would allow you to disable logging DEBUG/DEV level traces in the Release builds.
The single level of abstraction principle would favor doing all I/O in the same method instead of doing some at a high level and some at a low level of abstraction.
In other words, if you believe in that principle, keeping both input and output via cin/cout in the same method instead of showing some and hiding some is a good idea. It tends to give more readable code with less dependencies in each class.
According to the Single responsibility principle, the second option is preferred (any class should have exactly one responsibility, which is monitoring the temperature in your case, not outputting the results,) though you might want to set up another class to handle the temperature monitoring results (e.g. to write the results to a certain log file or something).
It's normal to have some way of logging information about your program.
It's also normal for this way to be, well, global.
Otherwise things just get too complicated when calling a method.
The only thing you should do to improve this is:
Have a logger class (or use an existing one) that can have its output stream set to whatever you choose (including std::out and an empty stream that doesn't print anything).
Ultimately, have a logger than can be hidden behind a #define so that it does not slow down code running in Release mode.
In my opinion in such cases you should not include cout into class, as maybe sometimes later you will need to output to the file or don't output at all. So if the cout is not put to the class you will have opportunity to reuse your class code without any changes.
Neither. Responsibility of main is to start the application with the command line arguments and to give a return value. Everything else should not be there. You might want to take a look at a book like "Object Design, Roles, Responsibilities, and Collaborations"

Do you really need a main() in C++?

From what I can tell you can kick off all the action in a constructor when you create a global object. So do you really need a main() function in C++ or is it just legacy?
I can understand that it could be considered bad practice to do so. I'm just asking out of curiosity.
If you want to run your program on a hosted C++ implementation, you need a main function. That's just how things are defined. You can leave it empty if you want of course. On the technical side of things, the linker wants to resolve the main symbol that's used in the runtime library (which has no clue of your special intentions to omit it - it just still emits a call to it). If the Standard specified that main is optional, then of course implementations could come up with solutions, but that would need to happen in a parallel universe.
If you go with the "Execution starts in the constructor of my global object", beware that you set yourself up to many problems related to the order of constructions of namespace scope objects defined in different translation units (So what is the entry point? The answer is: You will have multiple entry points, and what entry point is executed first is unspecified!). In C++03 you aren't even guaranteed that cout is properly constructed (in C++0x you have a guarantee that it is, before any code tries to use it, as long as there is a preceeding include of <iostream>).
You don't have those problems and don't need to work around them (wich can be very tricky) if you properly start executing things in ::main.
As mentioned in the comments, there are however several systems that hide main from the user by having him tell the name of a class which is instantiated within main. This works similar to the following example
class MyApp {
public:
MyApp(std::vector<std::string> const& argv);
int run() {
/* code comes here */
return 0;
};
};
IMPLEMENT_APP(MyApp);
To the user of this system, it's completely hidden that there is a main function, but that macro would actually define such a main function as follows
#define IMPLEMENT_APP(AppClass) \
int main(int argc, char **argv) { \
AppClass m(std::vector<std::string>(argv, argv + argc)); \
return m.run(); \
}
This doesn't have the problem of unspecified order of construction mentioned above. The benefit of them is that they work with different forms of higher level entry points. For example, Windows GUI programs start up in a WinMain function - IMPLEMENT_APP could then define such a function instead on that platform.
Yes! You can do away with main.
Disclaimer: You asked if it were possible, not if it should be done. This is a totally un-supported, bad idea. I've done this myself, for reasons that I won't get into, but I am not recommending it. My purpose wasn't getting rid of main, but it can do that as well.
The basic steps are as follows:
Find crt0.c in your compiler's CRT source directory.
Add crt0.c to your project (a copy, not the original).
Find and remove the call to main from crt0.c.
Getting it to compile and link can be difficult; How difficult depends on which compiler and which compiler version.
Added
I just did it with Visual Studio 2008, so here are the exact steps you have to take to get it to work with that compiler.
Create a new C++ Win32 Console Application (click next and check Empty Project).
Add new item.. C++ File, but name it crt0.c (not .cpp).
Copy contents of C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\crt\src\crt0.c and paste into crt0.c.
Find mainret = _tmain(__argc, _targv, _tenviron); and comment it out.
Right-click on crt0.c and select Properties.
Set C/C++ -> General -> Additional Include Directories = "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\crt\src".
Set C/C++ -> Preprocessor -> Preprocessor Definitions = _CRTBLD.
Click OK.
Right-click on the project name and select Properties.
Set C/C++ -> Code Generation -> Runtime Library = Multi-threaded Debug (/MTd) (*).
Click OK.
Add new item.. C++ File, name it whatever (app.cpp for this example).
Paste the code below into app.cpp and run it.
(*) You can't use the runtime DLL, you have to statically link to the runtime library.
#include <iostream>
class App
{
public: App()
{
std::cout << "Hello, World! I have no main!" << std::endl;
}
};
static App theApp;
Added
I removed the superflous exit call and the blurb about lifetime as I think we're all capable of understanding the consequences of removing main.
Ultra Necro
I just came across this answer and read both it and John Dibling's objections below. It was apparent that I didn't explain what the above procedure does and why that does indeed remove main from the program entirely.
John asserts that "there is always a main" in the CRT. Those words are not strictly correct, but the spirit of the statement is. Main is not a function provided by the CRT, you must add it yourself. The call to that function is in the CRT provided entry point function.
The entry point of every C/C++ program is a function in a module named 'crt0'. I'm not sure if this is a convention or part of the language specification, but every C/C++ compiler I've come across (which is a lot) uses it. This function basically does three things:
Initialize the CRT
Call main
Tear down
In the example above, the call is _tmain but that is some macro magic to allow for the various forms that 'main' can have, some of which are VS specific in this case.
What the above procedure does is it removes the module 'crt0' from the CRT and replaces it with a new one. This is why you can't use the Runtime DLL, there is already a function in that DLL with the same entry point name as the one we are adding (2). When you statically link, the CRT is a collection of .lib files, and the linker allows you to override .lib modules entirely. In this case a module with only one function.
Our new program contains the stock CRT, minus its CRT0 module, but with a CRT0 module of our own creation. In there we remove the call to main. So there is no main anywhere!
(2) You might think you could use the runtime DLL by renaming the entry point function in your crt0.c file, and changing the entry point in the linker settings. However, the compiler is unaware of the entry point change and the DLL contains an external reference to a 'main' function which you're not providing, so it would not compile.
Generally speaking, an application needs an entry point, and main is that entry point. The fact that initialization of globals might happen before main is pretty much irrelevant. If you're writing a console or GUI app you have to have a main for it to link, and it's only good practice to have that routine be responsible for the main execution of the app rather than use other features for bizarre unintended purposes.
Well, from the perspective of the C++ standard, yes, it's still required. But I suspect your question is of a different nature than that.
I think doing it the way you're thinking about would cause too many problems though.
For example, in many environments the return value from main is given as the status result from running the program as a whole. And that would be really hard to replicate from a constructor. Some bit of code could still call exit of course, but that seems like using a goto and would skip destruction of anything on the stack. You could try to fix things up by having a special exception you threw instead in order to generate an exit code other than 0.
But then you still run into the problem of the order of execution of global constructors not being defined. That means that in any particular constructor for a global object you won't be able to make any assumptions about whether or not any other global object yet exists.
You could try to solve the constructor order problem by just saying each constructor gets its own thread, and if you want to access any other global objects you have to wait on a condition variable until they say they're constructed. That's just asking for deadlocks though, and those deadlocks would be really hard to debug. You'd also have the issue of which thread exiting with the special 'return value from the program' exception would constitute the real return value of the program as a whole.
I think those two issues are killers if you want to get rid of main.
And I can't think of a language that doesn't have some basic equivalent to main. In Java, for example, there is an externally supplied class name who's main static function is called. In Python, there's the __main__ module. In perl there's the script you specify on the command line.
If you have more than one global object being constructed, there is no guarantee as to which constructor will run first.
If you are building static or dynamic library code then you don't need to define main yourself, but you will still wind up running in some program that has it.
If you are coding for windows, do not do this.
Running your app entirely from within the constructor of a global object may work just fine for quite awhile, but sooner or later you will make a call to the wrong function and end up with a program that terminates without warning.
Global object constructors run during the startup of the C runtime.
The C runtime startup code runs during the DLLMain of the C runtime DLL
During DLLMain, you are holding the DLL loader lock.
Tring to load another DLL while already holding the DLL loader lock results in a swift death for your process.
Compiling your entire app into a single executable won't save you - many Win32 calls have the potential to quietly load system DLLs.
There are implementations where global objects are not possible, or where non-trivial constructors are not possible for such objects (especially in the mobile and embedded realms).