Browse DevX
Sign up for e-mail newsletters from DevX


Managing Objects' Construction Order-2 : Page 2




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Advice on Code Organization
A properly organized C++ program consists of multiple source files and corresponding header files. A compilation unit, or unit for short, is a pair of a source file and its matching header file. Each unit may be compiled separately. Wouldn't it be better to group multiple classes in one unit? No, it wouldn't. In real world projects, each class may be maintained by a different developer, team or vendor. Splitting projects into separate compilation units has another advantage—reducing compilation time. Many compilers nowadays use incremental builds, meaning they compile only units that have changed since the last compilation.

Problem Analysis
Imagine an application that uses a log file class to record its activity for performance tuning, security purposes etc., In addition to the log file class, you also need an administrator class that sets the log file's path, controls users' authorizations etc. The first unit is implemented as follows:

// logfile.h //---------- #ifndef LOGFILE_H #define LOGFILE_H #include <fstream> #include <string> class Logfile { public: Logfile(const std::string & path); // private: std::ofstream log; std::string name; }; #endif // logfile.cpp //------------ #include "logfile.h" Logfile::Logfile(const std::string & path) :name(path) { log.open(name.c_str()); bool success=log; //.. } #include "admin.h" extern Admin admin; //admin is defined elsewhere //but needed here to construct the lf Logfile lf(admin.getfilename());

The application uses a global object called lf (defined in logfile.cpp). The reason for this is that lf should start logging before main() starts. The argument passed to lf's constructor is a path stored as an environment variable which class Admin retrieves. Obviously, admin must be constructed before lf. Class Admin is implemented in a separate unit like this:

// admin.h //--------- #if !defined(ADMIN_H) #define ADMIN_H #include <string> class Admin { public: Admin(); const std::string& getfilename() const; // private: std::string filename; }; #endif // admin.cpp //------------- #include "admin.h" Admin::Admin() { const char * pname=std::getenv("LOGFILE_PATH"); if(pname) //did getenv find a match? filename=pname; else //assign a default filename { filename = "activities.log"; } } const std::string& Admin::getfilename() const { return filename; } Admin admin;//global; must be constructed before lf

The application's body is implemented as a separate source file called main.cpp:

// main.cpp //----------- #include "logfile.h" extern Logfile lf; //declaration; defined in Logfile.cpp int main() { //...application code return 0; }

This example, like most short and didactic examples, is a bit artificial. However, the point is to show a real problem that occurs frequently in real projects.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date