The Envelope And Letter Idiom

Also known as delegated polymorphism.

Sometimes, one requires more dynamic behaviour than that conveniently offered by C++. Those who wish to enjor the performance and speed advantages of C++ and yet desire the flexibility of more dynamic languages can achieve it with a bit of work.

The class outlined below has a lot of characteristics similar to those of more dynamic languages. They allow objects to change their "type" at runtime, they allow objects to decide at runtime whether or not they "know what to do" with a particular request for a method invocation. This kind of framework is especially suited to classes that are loaded at run time. That's not a typo. I didn't mean "objects". You can indeed modify a program while it's running!

The following is an example of what James Coplien calls the Envelope and Letter Idiom. The class Envelope acts as a "bucket" in which to store other objects, namely "letters". Clients interact with the Envelope. This has some advantages:

If we want to avoid enormous numbers of stubbs like this one:

	return Rep -> someMethod();
in Envelope, we can do so by overloading operator-> as follows:
	Letter* operator->(){ return Rep; }
Then we can invoke methods on envelopes using the arrow syntax:

myEnvelope->method1();

We now proceed with a skeletal implementation.

Base Class Swapping

Statement of the problem

Suppose you have a class that inherits from two different classes, but you want to change which class you inherit from. The two classes have the same interface but different implementations.

First, it may have occured to you already that some varient on the envelope and letter idiom would be the right answer here. This indeed seems to be the most effective way to approach the problem. We discuss some of the possibilities.

Let's suppose the classes we want to inherit are Mother and Father, and their parent is Grandparent. Our new class will be called Child.

class Child 
{
    // put regular clas methods here.


    void reverse()
    {
        delete Interface;
        if ( male )
        {
            Interface = new Mother;
        }
        else
        {
            Interface = new Father;
        }
        male = (!male);
    }

Grandparent* operator->(){return Interface; }

private:
    Grandparent* Interface;
    bool male;

};

An in depth example

Once you're done with that, make sure you've read about registration, and come see a more in depth example.

Other Uses

Bibliography