mort
mort

Reputation: 13588

Where to document interfaces in C++?

I have more of a Java background, thus let me illustrate with a Java example. Say the following code exists:

interface iFoo {
    /* Do foo */
    void foo();
    /* Do bar */
    void bar();
}

class A implements iFoo {
    void foo() {};
    void bar() {};
}

class B<iFoo> {
    iFoo foo;
    B() {
        foo.foo();
        foo.bar(); 
    } 
} 

//somewhere in the code:
B b = new B<A>();

Now if I want to implement a class C that can be used as the type parameter for B, I know that C has to implement iFoo. Thus, I go there and by design-by-contract convention, all the necessary documentation will be there (which methods do I need to implement, what is there signature plus inline documentation.

In C++, it would look like this (correct me if I am wrong):

class A {
public:
     void foo();
     void bar();
}

template<class T>
class B {
public:
    T foo;
    B() {
        foo.foo();
        foo.bar(); 
    } 
} 

//somewhere in the code:
B *b = new B<A>();

Where is the best place to document what B expects of T? Or the other way around, if I have A and B and want to implement a class C that is passed as type parameter to B, how do I find out what B expects of T? The above is of course a very trivial example, just imagine bigger and more complex classes.

Upvotes: 1

Views: 342

Answers (4)

Some programmer dude
Some programmer dude

Reputation: 409196

In C++ a pure abstract interface class would look something like this:

struct IFoo
{
    virtual void foo() = 0;
    virtual void bar() = 0;

    virtual ~IFoo() {}
};

Then you inherit it like a normal class

class A : public IFoo
{
public:
    void foo();
    void bar();
};

Upvotes: 5

Kerrek SB
Kerrek SB

Reputation: 477100

I'd say a great place for documentation is the header file which defines the class. A user of your library will look at the header file to see the interface, and that's where she should find the documentation, both for the class or template as a whole and for the public members.

Both the class or template as a whole and each public member should have documentation detailing purpose, assumptions, preconditions etc.

Example:

foo.h:

// The "Foo" template implements a gizmo according to Smith, Jones et al.
// A Foo<T> can be used as a drop-in replacement for the usual Zip<T>.
//
// The template parameter T must be a complete object type which is
// assignable and copyable.
template <typename T>
class Foo
{
public:
    // Reflect the template parameters
    using type = T;
    using refence = T &;

    // Constructs a Foo with a given state of being active, a given age
    // and an identifier that represents its glurgh.
    Foo(bool active, int age, char id);

    // Perform the magic act of foo.
    // It is safe to call this function multiple times concurrently.
    // Returns the number of bars.
    //
    // Intended usage:
    //
    //    Foo x(false, 10, 'a');
    //    registerGlobally(x);
    //    x.activate();
    //    return x.perform();
    //
    int perform();

private:
    // ...
};

Ideally, absent other references, manuals or tutorials, a user should be able to work out how to use the class just from looking at the header. If you're disciplined and maintain a proper reference manual in parallel, you may be able to do without the examples, but the necessary information (meaning and requirements of parameters, meaning of return value) should be there.

When you inherit publicly from an abstract base class, this means of course that the base class contains all the interface documentation already, and you don't need to repeat the general information. However, you should still leave a short comment with the concrete overrides saying what they do specifically with respect to your implementation.


If you want template parameters to satisfy certain constraints, like being derived from a certain base class, you can enforce that programatically by using type traits, SFINAE and template metaprogramming. You should still document the requirements for template arguments in a human-readable form, but it is good hygiene to enforce such constraints in code.

Upvotes: 3

Karthik T
Karthik T

Reputation: 31952

You can use interfaces like Joachim suggests, but unfortunately, there is no way in C++ to enforce it, the way you would in Java. So you would have to document it as comments, say above the function or some such place.

Upvotes: 0

gbjbaanb
gbjbaanb

Reputation: 52679

You can do the same thing as interfaces in C++ by using virtual methods, put =0 at the end of the method definition and you have what is effectively an interface. (its actually a base class that you have to derive from as it cannot be instantiated itself and is called an 'abstract base class' in C++ terminology.).

But that gives you the answer, there's nothing stopping you from saying A is the base interface and using that as the definition of what 'B expects of T'. So if A has 2 methods, foo() and bar(), then that's what it supplies, and that's what all classes derived from A will have too.

Upvotes: 0

Related Questions