Literate Programming and Code Reuse
by Sverre Hendseth

The term "Literate Programming" describes the concept of mixing 
code and documentation introduced by Donald Knuth. The original 
system, "WEB system of structured documentation," was developed 
to provide the basis for the documentation/implementation of the 
TeX and MetaFont programs (see Knuth's "Literate Programming," 
Center for the Study of Language and Information (CSLI) Lecture 
notes number 27, 1992). WEB consists of two filters working on 
WEB source code; Tangle extracts compilable Pascal code, while 
Weave extracts the TeX-based documentation of the program. 

In this article, I'll look at ways in which literate programming 
helps you reorganize the layout of a program. When given the 
freedom to structure program layout as you wish, you tend to 
group parts of the code differently than as dictated by the 
language or compiler. Rather than grouping all public-function 
declarations of a C++ class together in the public section of the 
class, for instance, you might group each function declaration 
with the corresponding function implementation. I'll also examine 
how some of these new groups of code can be parameterized into 
reusable macros with the help of a simple macro processor. 
Specifically, I'll show how the application of design patterns 
such as Singleton and State from Design Patterns: Elements of 
Reusable Object-Oriented Software, by Erich Gamma et al. 
(Addison-Wesley, 1995), can be supported by such macros.

This article is a literate program in itself. The first part 
(available electronically) documents and implements a set of 
reusable macros, while the last part is an example of how these 
macros are used. Extracted C++ code from the example section of 
this article is presented in Listings One and Two. The tools and 
techniques described in this article have been used daily at TTS 
Automation for the past year and a half for the development of 
our offline robot programming systems.

The CLiP System for Literate Programming
The CLiP program (which was developed by E.W. van Ammers and M.R. 
Kramer and is available at ftp://sun01.info.wau.nl/clip/ for DOS, 
VMS, and UNIX) reads any number of ASCII files that have been 
extracted from documents that contain the program code and 
documentation (written with a word processor). From these, CLiP 
(short for "Code from Literate Programming") generates 
corresponding "source" files. Since CLiP is language independent, 
source files, make files, scripts/batch files, test data and the 
like can be generated from the same document(s). 

Two terms are central to understanding CLiP:

1.	A "stub" is a piece of text (code) copied to the output 
file. It is enclosed in the document with lines like: 

/*** <Name of Stub> ***/ 
	and 
/*** End of <Name of Stub> ***/

2.	A "slot" is a special line that can occur inside of any 
stub. It looks like the opening line of a stub and serves as a 
placeholder for the stub with the same name. The slot line will 
be replaced by the contents of this stub in the output file.

Both stubs and slots can have option specifiers prefixed with 
"#". The most important stub option is #file. The file stub has 
no stub name, but its contents are copied to the specified file:

/*** #file "extract.bat" #comment off ***/
rem Run the macro processor 
clipprep c:\litprog\litprog.txt >tmp.txt
rem Run CLiP
clp_env . . 
clp tmp.txt
/*** End of File ***/

The #comment option turns on or off comments generated by CLiP. 
The stub option #quick indicates that the stub is ended by the 
next blank line rather than the "End of" line.

The most frequently used slot option is #multiple (#mult), which 
allows more than one stub to be substituted for the slot. The 
#optional (#opt) slot option suppresses the warning if there is 
no stub to fit in a slot.

Stubs can come in any order in the CLiP source file. In a C++ 
class definition, for example, the member function declaration 
and its definition can be written in the same section. 
Alternatively, a data member declaration, its initialization in 
the constructor, the corresponding statements in the copy 
constructor and assignment operator, its access functions, and 
its destruction in the class's destructor can be placed in the 
same section of the source file. Listing Three is a CLiP source 
file with the corresponding generated code. 

When given the freedom to reorganize the layout of a program like 
this, it becomes apparent that structures--other than those 
traditionally thought of as reusable--repeat themselves. These 
range from trivialities like source file and class layout via 
member-variable handling, to complex design patterns like those 
described in Design Patterns or Jim Coplien's Advanced C++: 
Programming Styles and Idioms (Addison-Wesley, 1994).

The Macro Preprocessor
To enable reuse of these structures, you need a macro processor. 
The one I use, CLiPPrep (which is also available electronically), 
is a filter, expanding macros of the forms:

* Parameterless macro
%MacroName

* Macro call with parameters
%MacroName(par1,par2,par3)

The macro call will be substituted by the macro's body. A macro 
parameter in this form may contain any characters except "," and 
")". If these characters are needed in the parameter, you must 
enclose the parameter with named brackets of the form %x{ and 
%x}, where x can be any letter or digit, or can be omitted. These 
brackets must be matched and may not contain any closing brackets 
with the same name. This is a legal macro call:

%OneParameterMacro(%a{
This parameter may contain ',' and ')'
It also contains three EndOfLines.
%a})

One of the predefined macros is DefMacro, which registers a new 
macro. It takes at least two parameters, the first being the 
macro name, and the last the macro body. The optional middle 
parameters are the parameter names of the new macro. These are 
referenced from the macro body like parameterless macros.

Below is a macro that defines the layout of a C++ class 
declaration. A class has a name and may inherit another class. I 
assume only public and nonmultiple inheritance to keep the 
examples simple. 

%DefMacro(Class,class,baseClass,%{
class %class %If(%baseClass,: public %baseClass,){
public:
 /*** %class public props #mult #opt ***/
protected:
 /*** %class protected props #mult #opt ***/
private:
 /*** %class private props #mult #opt ***/
};
%})

If is a predefined macro that evaluates to one out of two bodies 
depending on whether or not its first parameter is the empty 
string. The call %Class(CMyClass,CObject) expands to:

class CMyClass : public CObject {
public:
 /*** CMyClass public props #mult #opt ***/
protected:
 /*** CMyClass protected props #mult #opt ***/
private:
 /*** CMyClass private props #mult #opt ***/
};

The class's properties will be filled in by stubs elsewhere in 
the document. 

Reusing the Repeating Structures
Before describing how design patterns are supported, I need to 
define two more macros.

DefineClass defines corresponding header and implementation files 
for a class, using the previous Class macro for the class 
declaration itself. It takes the filename base, class name, and 
base class name as parameters. The header file contains one slot 
for includes, one for declarations, and the class declaration 
itself--everything surrounded by an #ifndef statement. The 
implementation file includes the corresponding header file and 
has a slot for its own includes, and a slot for the 
implementation itself:

%DefMacro(DefineClass,file,class,baseClass,%a{
%%% Make the header file
/*** #file "%file.hpp" #comment off ***/
#ifndef INCLUDE_%file
#define INCLUDE_%file
/*** %class header includes #mult #opt ***/
/*** %class declarations #mult #opt ***/
%Class(%class,%baseClass)
#endif
/*** End Of File ***/
%%% Now for the implementation file
/*** #file "%file.cpp" #comment off ***/
#include "%file.hpp"
/*** %class implementation includes #mult #opt ***/
/*** %class implementation #mult #opt ***/
/*** End Of File ***/
%a})

The second basic macro is the member function. A member function 
is contained in a class and has a name, access (public, 
protected, private), parameters, return value, possibly a type 
modifier (virtual or static), and body. Again, to keep the 
example simple, I ignore pure virtual functions, overloading, 
default values of parameters, const functions, and the like. The 
macro puts the function declaration into the correct slot in the 
class declaration, and the function implementation into the 
implementation file, opening a "<functionName> actions" slot for 
the function body:

%DefMacro(Method,class,scope,typeMod,type,name,pars,
%a{
%%% Make the prototype 
/*** %class %scope props ***/
%typeMod %type %name (%pars);
/*** End of %class %scope props ***/
%%% Make the definition
/*** %class implementation ***/
%type
%class::%name (%pars){
 /*** %class::%name actions #mult #opt ***/
}
/*** End of %class implementation ***/
%a})

The Singleton Pattern
By protecting the constructor and letting all access to the 
object go through a static member function, the Singleton pattern 
ensures that there is only one instance of a class created. The 
following macro adds a private constructor to the class, a 
private static object pointer to the single instance of the 
class, and a static public member function Instance() that 
returns the instance pointer, if necessary, after creating the 
object. 

%DefMacro(MakeSingleton,class,
%a{
%%% The private constructor
%Method(%class,private,,,%class,)
%%% The static instance pointer
/*** %class private props ***/
static %class * m_instance;
/*** End of %class private props ***/
%%% ...and its definition 
/*** %class implementation ***/
%class * %class::m_instance = NULL;
/*** End of %class implementation ***/
%%% The Instance() function
%Method(%class,public,static,%class *,Instance,)
%%% and its body
/*** %class::Instance actions ***/
if(m_instance == NULL){
 m_instance = new %class;
}
return m_instance;
/*** End of %class::Instance actions ***/
%a})

This is a simple macro to build; it adds a set of features to an 
already existing class. Listing Four is the result of the two 
macro calls, partly evaluated by CLiP:

%DefineClass(mysing,CMySingleton,)
%MakeSingleton(CMySingleton) 

The Abstract Base Class 
When you have several classes that should implement the same 
interface, or if you want to achieve a proper division between 
interface and implementation for one class in C++, you define the 
interface as an abstract base class (ABC) which the 
implementation classes inherit. I will describe a variant of this 
structure where the subclasses are declared in the implementation 
file of the base class; that is, they are completely invisible 
from the client side. Instances of these classes might, for 
example, be created through static functions in the abstract base 
class.

This is more a feature of the C++ language than an idiom or 
design pattern, but it occurs frequently and contains features 
coded in its layout (the concrete classes are invisible because 
they are declared in the implementation file). Macros can also 
help ensure consistency between the base class and concrete 
classes. Therefore, this structure is a good candidate to 
implement as a reusable macro. Listing Five presents the layout 
of the header and implementation file. 

Four macros describe this structure:

1. ABC(class) prepares the given class as an abstract base 
class, giving it a virtual destructor and partitioning the 
implementation file:

%DefMacro(ABC,class,%{
%%% The virtual destructor
%Method(%class,public,virtual,,~%class,)
%%% The slot for the sub-class declarations
/*** %class implementation ***/
/*** %class derived classes #mult #opt ***/
/*** %class child implementations #mult #opt ***/
/*** End of %class implementation ***/
%})

2. ABCMethod(class,returnType,name,parameters) adds the 
specified method to the interface as a pure virtual function and 
remembers (defines as macros) the return value and parameters:

%DefMacro(ABCMethod,class,type,name,pars,%{
%%% Define the method
/*** %class public props ***/
virtual %type %name (%pars) = 0;
/*** End of %class public props ***/
%%% Remember the return type and parameters.
%DefMacro(%name ReturnType,%type)
%DefMacro(%name Parameters,%pars)
%})

3. ABCDerivedClass(baseClass,class) defines an 
implementation class inheriting the ABC and defines the slot for 
its implementation:

%DefMacro(ABCDerivedClass,baseClass,class,%a{
%%% The subClass
/*** %baseClass derived classes ***/
%Class(%class,%baseClass)
/*** End of %baseClass derived classes ***/
%%% Make the slot for the sub-class implementation
/*** %baseClass child implementations ***/
/*** %class implementation #mult #opt ***/
/*** End of %baseClass child implementations ***/
%a})

4. ABCDerivedClassMethod(class,name) looks up the stored 
return value and the parameters of the method and defines them in 
the class:

%DefMacro(ABCDerivedClassMethod,class,name,
%x{
%Method(%class,public,virtual,
 %{%Eval(%% %name ReturnType)%},%name,
 %{%Eval(%% %name Parameters)%})
%x})

The Eval macro takes one parameter and evaluates it one extra 
time, and the "%%" constellation evaluates to a single "%".

Remember that function bodies, member variables, helper 
functions, and the like are added to the classes in the normal 
manner, using the Method macro or writing stubs that fit in the 
appropriate slots.

The State Pattern 
You can organize the state-dependent behavior of a class, (the 
"context") by forwarding requests for this behavior to a 
contained instance of a State class. This State class is an 
abstract base class and the instance variable is changed to point 
to different implementations for different states. Here, I'll 
describe a variant of this pattern, where the state objects do 
not have data members. The context's "this" pointer can, however, 
be passed with every function call to the state objects so that 
they can access the context's data if necessary. The concrete 
state classes are thereby modeled as Singletons. This pattern is 
divided into two macros:

1. AddState(contextClass,stateId) adds a state variable to 
the context class and defines the state ABC. It remembers the 
context class corresponding to the stateId (sId). The state class 
name is chosen to be the stateId prefixed by "C":

%DefMacro(AddState,context,sId,
%{
%%% Define the State Base Class in the 
%%% implementation file of the context.
/*** %context implementation ***/
%Class(C%sId,)
/*** C%sId implementation #mult #opt ***/
/*** End of %context implementation ***/
%%% Make it an ABC
%ABC(C%sId)
%%% We have to declare it.
/*** %context Declarations ***/
class C%sId;
/*** End of %context Declarations ***/
%%% Making the variable
/*** %context private props ***/
C%sId * m_%sId;
/*** End of %context private props ***/
%%% Remember the context corresponding to the sId
%DefMacro(%sId Context,%context)
%})

2. DefineState(sId,stateName) defines a class that inherits 
the state base class. It calls ABCDerivedClass and makes it a 
Singleton. It is also a friend of the context. 

%DefMacro(DefineState,sId,name,%a{
%ABCDerivedClass(C%sId,%name)
%MakeSingleton(%name)
/*** %Eval(%% %sId Context) public props ***/
friend class %name;
/*** End of %Eval(%% %sId Context) public props ***/
%a})

The macros ABCMethod and ABCDerivedClassMethod are used to add 
methods to the interface and to the concrete states. 

Using the Macros
Assume that, up to this point, this article is in a separate file 
and is maintained as a reusable module. The text is included in 
this section by the macro processor's Include(fileName) macro. 
The code generated from this part of the article is presented in 
Listings One and Two.

Assume an application comprised of a number of geometric entity 
classes that know how to draw themselves as wireframes, in terms 
of functions offered by the CGl class. The entity instances may 
be ordered hierarchically in that more-primitive or lower-level 
entities may be a part of a higher-level entity. 

The CGl class makes the interface to the OpenGL graphics library 
and implements the functions relating to color control. 
Consequently, you want the following functionality:

* If an entity does not set the color before issuing drawing 
commands, it should be drawn in the current color (that is, the 
color set by its parent entity). 
* A parent entity should be able to override the color commands 
of its subobjects.
* When highlighting an entity, all subentities should also be 
drawn in the highlight color, overriding their color commands.
* When doing dummy draws not shown on the screen (picking or 
collecting statistics, for instance), color commands should be 
ignored.

The functions PushColor, PopColor, LockColor, and UnlockColor 
perform these tasks. Each works differently, depending on whether 
the color is in the state "Locked" or "Normal". 

I'll start by defining the CGl class, states, and interface 
functions:

%DefineClass(glclass,CGl,CObject)
%%% Add Some Includes
/*** CGl header includes ***/
#include <afxwin.h>
#include <gl.h>
#include "ccolor.hpp"
/*** End of CGl header includes ***/
%%% Add the state variable and the states
%AddState(CGl,ColorMode)
%DefineState(ColorMode,CLocked)
%DefineState(ColorMode,CNormal)
%%% Then the four methods
%ABCMethod(CColorMode,void,PushColor,%{
 CGl * pC,
 const CColor & color
%})
%ABCMethod(CColorMode,void,PopColor,CGl * pC)
%ABCMethod(CColorMode,void,LockColor,CGl * pC)
%ABCMethod(CColorMode,void,UnlockColor,CGl * pC)

The start state must be set. Since the constructor of CGl is not 
already defined, you must do that too:

%Method(CGl,public,,,CGl,)
/*** CGl::CGl actions #quick ***/
m_ColorMode = CNormal::Instance();

Use the following code to keep track of a stack of colors, and 
the number of times LockColor is called:

/*** CGl private props #quick ***/
int lockLevel;
CObList colorList; // Used for implementing a stack

PushColor and PopColor do nothing in Locked mode, but must 
maintain the stack of colors and set the current color in Normal 
mode:

%ABCDerivedClassMethod(CLocked,PushColor)
%ABCDerivedClassMethod(CLocked,PopColor)
%ABCDerivedClassMethod(CNormal,PushColor)
/*** CNormal::PushColor actions #quick ***/
pC->colorList.AddHead(new CColor(color));
glColor3d(color.R(),color.G(),color.B());
%ABCDerivedClassMethod(CNormal,PopColor)
/*** CNormal::PopColor actions #quick ***/
delete pC->colorList.RemoveHead();
CColor * pColor = (CColor *) pC->colorList.GetHead();
glColor3d(pColor->R(),pColor->G(),pColor->B());

LockColor switches modes and initiates the lockLevel to 1 (if in 
Normal mode) and increments the lockLevel (if in Locked mode):

%ABCDerivedClassMethod(CNormal,LockColor)
/*** CNormal::LockColor actions #quick ***/
pC->lockLevel = 1;
pC->m_ColorMode = CLocked::Instance();
%ABCDerivedClassMethod(CLocked,LockColor)
/*** CLocked::LockColor actions #quick ***/
pC->lockLevel++;

UnlockColor should decrement the lockLevel and change mode if it 
reaches zero while in Locked mode, and assert if in Normal mode:

%ABCDerivedClassMethod(CNormal,UnlockColor)
/*** CNormal::UnlockColor actions #quick ***/
ASSERT(0);
%ABCDerivedClassMethod(CLocked,UnlockColor)
/*** CLocked::UnlockColor actions #quick ***/
pC->lockLevelQ;
if(pC->lockLevel == 0){
 pC->m_ColorMode = CNormal::Instance();
}

Now you need to to reflect these functions out to the CGl class:

%Method(CGl,public,,void,PushColor,const CColor & c)
/*** CGl::PushColor actions #quick ***/
m_ColorMode->PushColor(this,c);
%Method(CGl,public,,void,PopColor,)
/*** CGl::PopColor actions #quick ***/
m_ColorMode->PopColor(this);
%Method(CGl,public,,void,LockColor,)
/*** CGl::LockColor actions #quick ***/
m_ColorMode->LockColor(this);
%Method(CGl,public,,void,UnlockColor,)
/*** CGl::UnlockColor actions #quick ***/
m_ColorMode->UnlockColor(this);

Conclusion
Traditional drawbacks to literate programming include: 

* Increased "distance" between the file you are creating and the 
results of compilation/testing. This is an inconvenience if your 
programming style includes frequent compilation.
* Less powerful version control if you save source as a binary 
file (as with most modern word processors). 
* Loss of IDE features.

Still, you get a system that encourages and enables good source-
code documentation and intuitive layout.

The concept of combining a macro processor with literate 
programming is very expressive. For C++, it surpasses the 
expressiveness of templates. It is also applicable to most other 
programming languages. Weaknesses are mainly related to the 
correctness of the extraction. For example, even if you 
incorrectly name a stub, you may not get a warning, and the 
resulting modules may still compile. 

For more information on literate programming, see the 
comp.programming.literate FAQ at ftp://ftp.th-darmstadt.de/ 
pub/programming/literate-programming and the author's home page 
at http://home.sol.no/tts/sh. 



Listing One

#ifndef INCLUDE_glclass
#define INCLUDE_glclass
#include <afxwin.h>
#include <gl.h>
#include "ccolor.hpp"
class CColorMode;

class CGl: public CObject{
public:
  friend class CLocked;
  friend class CNormal;
    CGl();
   void PushColor(const CColor & c);
   void PopColor();
   void LockColor();
   void UnlockColor();
protected:
private:
  CColorMode * m_ColorMode;
  int lockLevel;
  CObList colorList; // Used for implementing a stack
};
#endif


Listing Two

#include "glclass.hpp"

class CColorMode{
public:
  virtual  ~CColorMode();
  virtual void PushColor(
    CGl * pC,
    const CColor & color
  ) = 0;
  virtual void PopColor(CGl * pC) = 0;
  virtual void LockColor(CGl * pC) = 0;
  virtual void UnlockColor(CGl * pC) = 0;
protected:
private:
};
CColorMode::~CColorMode(){
}
class CLocked: public CColorMode{
public:
  static CLocked* Instance();
  virtual void PushColor(
    CGl * pC,
    const CColor & color
  );
  virtual void PopColor(CGl * pC);
  virtual void LockColor(CGl * pC);
  virtual void UnlockColor(CGl * pC);
protected:
private:
    CLocked();
  static CLocked* m_instance;
};
class CNormal: public CColorMode{
public:
  static CNormal* Instance();
  virtual void PushColor(
    CGl * pC,
    const CColor & color
  );
  virtual void PopColor(CGl * pC);
  virtual void LockColor(CGl * pC);
  virtual void UnlockColor(CGl * pC);
protected:
private:
    CNormal();
  static CNormal* m_instance;
};
CLocked::CLocked(){
}
CLocked* CLocked::m_instance = NULL;
CLocked*
CLocked::Instance(){
  if(m_instance == NULL){
    m_instance = new CLocked;
  }
  return m_instance;
}
void
CLocked::PushColor(
  CGl * pC,
  const CColor & color
){
}
void
CLocked::PopColor(CGl * pC){
}
void
CLocked::LockColor(CGl * pC){
  pC->lockLevel++;
}
void
CLocked::UnlockColor(CGl * pC){
  pC->lockLevel--;
  if(pC->lockLevel == 0){
    pC->m_ColorMode = CNormal::Instance();
  }
}
CNormal::CNormal(){
}
CNormal* CNormal::m_instance = NULL;
CNormal*
CNormal::Instance(){
  if(m_instance == NULL){
    m_instance = new CNormal;
  }
  return m_instance;
}
void
CNormal::PushColor(
  CGl * pC,
  const CColor & color
){
  pC->colorList.AddHead(new CColor(color));
  glColor3d(color.R(),color.G(),color.B());
}
void
CNormal::PopColor(CGl * pC){
  delete pC->colorList.RemoveHead();
  CColor * pColor = (CColor *) pC->colorList.GetHead();
  glColor3d(pColor->R(),pColor->G(),pColor->B());
}
void
CNormal::LockColor(CGl * pC){
  pC->lockLevel = 1;
  pC->m_ColorMode = CLocked::Instance();
}
void
CNormal::UnlockColor(CGl * pC){
  ASSERT(0);
}
CGl::CGl(){
  m_ColorMode = CNormal::Instance();
}
void
CGl::PushColor(const CColor & c){
  m_ColorMode->PushColor(this,c);
}
void
CGl::PopColor(){
  m_ColorMode->PopColor(this);
}
void
CGl::LockColor(){
  m_ColorMode->LockColor(this);
}
void
CGl::UnlockColor(){
  m_ColorMode->UnlockColor(this);
}


Listing Three 

----- ccolor.doc ----------------
A class that stores the RGB values of a color.
/*** #file "ccolor.hpp" #comment off ***/
class CColor: public CObject {
public: 
  /*** CColor public props #mult #opt ***/
private: 
  /*** CColor private props #mult #opt***/
};
/*** End of File ***/

The data members:
/*** CColor private props #quick ***/
int m_r; int m_g; int m_b;

We need a constructor that allows setting these;
/*** CColor public props #quick ***/
CColor(int r,int g,int b);

/*** CColor public props #quick ***/
int R()const;int G()const;int B()const;
--------------------------

----- ccolor.hpp ---------------
class CColor: public CObject {
public:
  CColor(int r,int g,int b);
  int R();int G();int B();
private:
  int m_r; int m_g; int m_b;
};
--------------------------


Listing Four

----- mysing.hpp: ----------
#ifndef INCLUDE_mysing
#define INCLUDE_mysing

/*** CMySingleton header includes #mult #opt ***/
/*** CMySingleton declarations #mult #opt ***/
class CMySingleton{
public:
  static CMySingleton* Instance();
  /*** CMySingleton public props #mult #opt ***/
protected:
  /*** CMySingleton protected props #mult #opt ***/
private:
  CMySingleton();
  static CMySingleton* m_instance;
  /*** CMySingleton private props #mult #opt ***/
};
#endif
-------------------------

----- mysing.cpp: ----------
#include "mysing.hpp"
/*** CMySingleton implementation includes #mult #opt ***/

CMySingleton::CMySingleton(){
  /*** CMySingleton::CMySingleton actions #mult #opt ***/
}
CMySingleton* CMySingleton::m_instance = NULL;

CMySingleton*
CMySingleton::Instance(){
  if(m_instance == NULL){
    m_instance = new CMySingleton;
  }
  return m_instance;
}
/*** CMySingleton implementation #mult #opt ***/
-------------------------


Listing Five

----- myabc.hpp: ----------
#ifndef INCLUDE_myabc
#define INCLUDE_myabc

/*** CABC header includes #mult #opt ***/
/*** CABC declarations #mult #opt ***/
class CABC{
public:
  virtual  ~CABC();
  /*** CABC public props #mult #opt ***/
protected:
  /*** CABC protected props #mult #opt ***/
private:
  /*** CABC private props #mult #opt ***/
};
#endif
-------------------------

----- myabc.cpp: ----------
#include "myabc.hpp"
/*** CABC implementation includes #mult #opt ***/
CABC::~CABC(){
}
/*** CABC derived classes #mult #opt ***/
/*** CABC child implementations #mult #opt ***/
/*** CABC implementation #mult #opt ***/
-------------------------


