Code - organizing files in c

From NoskeWiki
Jump to: navigation, search

A Quick Explanation of Organizing Files in C and C++

Main reasons to split code into files

  1. Speed up compilation (only modified files need to be recompiled)
  2. Increase organization (easier to find functions)
  3. Facilitate code reuse (can copy appropriate modules/files in another project)
  4. Share code between projects (as above, but without copying the files)
  5. Split coding responsibilities among programmers (when programming in a team)
  6. A single file is simply unmanageable for complex projects


How to split files

  • Look to split code into logical module divisions.
  • Each section / struct / class should have its own source (.cpp) and header (.h) file.



The HEADER file:

  • Include the DECLARATIONS of all class variables & methods and all functions & global variables
    • The exception of this is INLINE functions and TEMPLATE functions - most compilers need these DEFINED in the header.
  • Always use inclusion guard (to prevent multiple inclusions of the header into another file)
  • Be sure to #include all dependent files - only include header files (never .cpp files) and use forward declarations where possible.
    • The DEFINITON of any constants (including enums)

The SOURCE file should contain:

  • The DEFINITION of all class methods, functions and global variables
    • NOTE: This will not include definitions for inline and template functions... nor for consts and enums.
  • An include of the header file.

EXAMPLE OF A STRUCTURE:

Point.h:

#ifndef INC_POINT_H      // Inclusion guard.
#define INC_POINT_H      // Inclusion guard.
 
struct Point
{
  float x, y;                 // Variables (NOTE: you cannot initialize class variables unless static / const).
 
  Point();                     // Default constructor.
  void scale(float factor);    // Method declaration.
}
 
#endif                         // Inclusion guard.

Point.cpp:

#include "Point.h"        // Always include the header of each source file.
 
Point::Point() {       
  x = 10;                 // Default values are put in the default constructors.
  y = 10;
}
void Point::scale (float factor) {
  x *= factor;
  y *= factor;
}



EXAMPLE OF GLOBAL VARIABLES AND FUNCTIONS:

common_functions.h:

#ifndef INC_COMMON_FUNCTIONS_H        // Inclusion guard.
#define INC_COMMON_FUNCTIONS_H        // Inclusion guard.
 
#include <string>                     // Include list of dependencies.
using namespace std;
 
const double PI = 3.141592654;        // Constants are defined.
 
bool keySpaceBarDown;                 // Global variables are declared.
...
 
void stringToLowerCase(string &s);    // Function are declared.
double calcVolumeSphere(const double radius);
...
 
template <typename type>              // An exception is inline and template functions, which are declared.
type SQ(const type x) {
  return (x*x);
}        
 
inline void updateMax(int &max, const int newVal) {
  if(max < newVal)
    max = newVal;
}
 
#endif /*INC_COMMON_FUNCTIONS_H*/


common_functions.cpp:

#include "common_functions.h"
 
#include <algorithm>                // Defined here because we don't need transform in header.
 
 
keySpaceBarDown = false;            // Define variables with default value in .cpp.
...
 
void string_toLowerCase(string &s)     // Declare functions in source file.
{
  std::transform(s.begin(), s.end(), s.begin(), tolower);
}
 
double geom_volumeSphere(const double radius)
{
  return (4.0/3.0 * PI * (radius*radius*radius));
}
...


Links