Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Thinking in C++
Prev Contents / Index Next

Reducing recompilation

The project manager in your programming environment will cause a recompilation of a file if that file is touched (that is, modified) or if another file it’s dependent upon – that is, an included header file – is touched. This means that any time you make a change to a class, whether it’s to the public interface or to the private member declarations, you’ll force a recompilation of anything that includes that header file. This is often referred to as the fragile base-class problem. For a large project in its early stages this can be very unwieldy because the underlying implementation may change often; if the project is very big, the time for compiles can prohibit rapid turnaround.

The technique to solve this is sometimes called handle classes or the “Cheshire cat”[37] – everything about the implementation disappears except for a single pointer, the “smile.” The pointer refers to a structure whose definition is in the implementation file along with all the member function definitions. Thus, as long as the interface is unchanged, the header file is untouched. The implementation can change at will, and only the implementation file needs to be recompiled and relinked with the project.

Here’s a simple example demonstrating the technique. The header file contains only the public interface and a single pointer of an incompletely specified class:

//: C05:Handle.h
// Handle classes
#ifndef HANDLE_H
#define HANDLE_H

class Handle {
  struct Cheshire; // Class declaration only
  Cheshire* smile;
public:
  void initialize();
  void cleanup();
  int read();
  void change(int);
};
#endif // HANDLE_H ///:~

This is all the client programmer is able to see. The line

struct Cheshire;

is an incomplete type specification or a class declaration (A class definition includes the body of the class.) It tells the compiler that Cheshire is a structure name, but it doesn’t give any details about the struct. This is only enough information to create a pointer to the struct; you can’t create an object until the structure body has been provided. In this technique, that structure body is hidden away in the implementation file:

//: C05:Handle.cpp {O}
// Handle implementation
#include "Handle.h"
#include "../require.h"

// Define Handle's implementation:
struct Handle::Cheshire {
  int i;
};

void Handle::initialize() {
  smile = new Cheshire;
  smile->i = 0;
}

void Handle::cleanup() {
  delete smile;
}

int Handle::read() {
  return smile->i;
}

void Handle::change(int x) {
  smile->i = x;
} ///:~

Cheshire is a nested structure, so it must be defined with scope resolution:

struct Handle::Cheshire {

In Handle::initialize( ), storage is allocated for a Cheshire structure, and in Handle::cleanup( ) this storage is released. This storage is used in lieu of all the data elements you’d normally put into the private section of the class. When you compile Handle.cpp, this structure definition is hidden away in the object file where no one can see it. If you change the elements of Cheshire, the only file that must be recompiled is Handle.cpp because the header file is untouched.

The use of Handle is like the use of any class: include the header, create objects, and send messages.

//: C05:UseHandle.cpp
//{L} Handle
// Use the Handle class
#include "Handle.h"

int main() {
  Handle u;
  u.initialize();
  u.read();
  u.change(1);
  u.cleanup();
} ///:~

The only thing the client programmer can access is the public interface, so as long as the implementation is the only thing that changes, the file above never needs recompilation. Thus, although this isn’t perfect implementation hiding, it’s a big improvement.

Thinking in C++
Prev Contents / Index Next

 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire