Interface Classes in C++

By David R. Tribble
Revision 1.0, 2007-02-16

Class Foo below is declared as an interface class. Such classes do not contain any members variables or private functions, but contain only non-private member functions, static functions, constants, and static variables. In other words, they provide only interface behaviors (functions) to clients that will use the class, and do not contain any implementation details (variables or private functions).

// foo.hpp [public]
class Foo
{
public:
    static Foo *        create();                   // Constructor

    virtual /**/        ~Foo();                     // Destructor

    virtual int         func1();                    // Method 1
    virtual int         func2(int x);               // Method 2

protected:
    /**/                Foo();                      // Default constructor
    /**/                Foo(const Foo &o);          // Copy constructor
    const Foo &         operator =(const Foo &o);   // Assignment
};

This interface class provides a creation function, create(), and two implementation functions, func1() and func2(). The class contains very little else, and in particular contains no member variables. This is the defining feature of an interface class, that it provides only virtual member functions, which implement the behavior of the interface. Note in particular that the class destructor function is virtual, which is necessary to insure that objects that implement the interface, and which presumably contain member variables, are properly deallocated when their lifetime (scope) ends.

Clients of the interface class do not have direct access to any of the internal state (e.g., member variables) of classes that implement the interface class. The code below is a client of the interface class.

// client.cpp
#include "foo.hpp"

void clientFunc()
{
    Foo *   obj;

    // Create a Foo object
    obj = Foo::create();

    // Call the interface methods
    obj->func1();
    obj->func2(123);

    // Dispose of the Foo object
    delete obj;
}

The creation function Foo::create() instantiates an object that is actually of a class type derived from (i.e., a subclass type of) the interface class. In this example, the actual type is class FooImpl (shown below). Clients of the interface are not aware of this, however, and can only treat it as an object of the interface class type.

Class FooImpl below implements interface class Foo.

// fooimpl.hpp [private]
#include "foo.hpp"

class FooImpl: public Foo
{
public:
    virtual /**/        ~FooImpl();                 // Destructor
    /**/                FooImpl();                  // Default constructor

    virtual int         func1();                    // Method 1
    virtual int         func2(int x);               // Method 2

private:
    int                 m_var1;                     // Member 1
    int                 m_var2;                     // Member 2

private:
    int                 helper1(int x);             // Helper method 1
};

This implementation class contains the member variables, helper functions, and so forth that are needed to actually implement the behavior of the interface class. These implementation details, however, are not exposed to the client. Clients have access only to the class members declared in the interface class.

// fooimpl.cpp
#include "fooimpl.hpp"

/*static*/
Foo * Foo::create()
{
    return (new FooImpl());
}

FooImpl::~FooImpl()
{
    ...
}

FooImpl::FooImpl():
    m_var1(0),
    m_var2(0)
{
    ...
}

int FooImpl::func1()
{
    ...
}

int FooImpl::func2(int x)
{
    ...
}

int FooImpl::helper1(int x)
{
    ...
}

The code for the implementation class must provide a base class creation function, create(), which instantiates objects of the implementation class type. This is done simply by calling the constructor for the implementation class.

The compiled object code module for the implementation source file (e.g., fooimpl.obj or fooimpl.o) provides all of the functionality (virtual functions) of the interface class, as well as providing a constructor (the create() function). When this object module is linked into the executable program, it provides the complete implementation of the interface subclass.

In addition, separating the interface and the implementation source code in this fashion allows the programmer to write more than one implementation subclass that implements the interface class, and each implementation is then provided as a separate object module. This can be useful when the interface must be provided for different implementations, where each implementation subclass is tailored to a specific application. The programmer can then link in the object module with his application program that is the most appropriate for his particular programming solution.


Copyright ©2007 by David R. Tribble, all rights reserved.
Permission is granted to reference, quote, and link to this document provided that appropriate credit is given to the author.

This file: http://david.tribble.com/text/implclass.html