views:

24724

answers:

9

How do I setup a class that represents an interface? Is this just an abstract base class?

+27  A: 

Make a class with pure virtual methods. Use the interface by creating another class that overrides those virtual methods.

A pure virtual method is a class method that is defined as virtual and assigned to 0.

class IDemo
{
    public:
        virtual void OverrideMe() = 0;
}

class Child : public IDemo
{
    public:
        virtual void OverrideMe()
        {
            //do stuff
        }
}
bradtgmurray
you should have a do nothing destructor in IDemo so that it is defined behavior to do: IDemo *p = new Child; /*whatever */ delete p;
Evan Teran
+14  A: 

The whole reason you have a special Interface type-category in addition to abstract base classes in C#/Java is because C#/Java do not support multiple inheritance.

C++ supports multiple inheritance, and so a special type isn't needed. An abstract base class with no non-abstract (pure virtual) methods is functionally equivalent to a C#/Java interface.

Joel Coehoorn
+45  A: 

To expand on the answer by bradtgmurray, you may want to make one exception to the pure virtual method list of your interface by adding a virtual destructor. This allows you to pass pointer ownership to another party without exposing the base class. The destructor doesn't have to do anything, because the interface doesn't have any concrete members. It might seem contradictory to define a function as both virtual and inline, but trust me - it isn't.

class IDemo
{
    public:
        virtual ~IDemo() {}
        virtual void OverrideMe() = 0;
};

class Parent
{
    public:
        virtual ~Parent();
};

class Child : public Parent, public IDemo
{
    public:
        virtual void OverrideMe()
        {
            //do stuff
        }
};
Mark Ransom
Virtual desctuctor++! This is very important.You may also want to include pure virtual declarations of the operator= and copy constructor definitions to prevent the compiler auto-generating those for you.
xan
An alternative to a virtual destructor is a protected destructor. This disables polymorphic destruction, which may be more appropriate in some circumstances. Look for "Guideline #4" in http://www.gotw.ca/publications/mill18.htm.
Fred Larson
If you know you're not going to delete the class through a base class, you don't need the virtual destructor. However, it's never really harmful to make the destructor virtual anyway (except for one vtable lookup, oh no!).
bradtgmurray
One other option is to define a pure virtual (`=0`) destructor with a body. The advantage here is that the compiler can, theoretically, see that vtable has no valid members now, and discard it altogether. With a virtual destructor with a body, said destructor can be called (virtually) e.g. in the middle of construction via `this` pointer (when constructed object is still of `Parent` type), and therefore the compiler has to provide a valid vtable. So if you don't explicitly call virtual destructors via `this` during construction :) you can save on code size.
Pavel Minaev
+7  A: 

There is no concept of "interface" per se in C++. AFAIK, interfaces were first introduced in Java to work around the lack of multiple inheritance. This concept has turned out to be quite useful, and the same effect can be achieved in C++ by using an abstract base class.

An abstract base class is a class in which at least one member function (method in Java lingo) is a pure virtual function declared using the following syntax:


class A
{
  virtual void foo() = 0;
};

An abstract base class cannot be instantiated, i. e. you cannot declare an object of class A. You can only derive classes from A, but any derived class that does not provide an implementation of foo() will also be abstract. In order to stop being abstract, a derived class must provide implementations for all pure virtual functions it inherits.

Note that an abstract base class can be more than an interface, because it can contain data members and member functions that are not pure virtual. An equivalent of an interface would be an abstract base class without any data with only pure virtual functions.

And, as Mark Ransom pointed out, an abstract base class should provide a virtual destructor, just like any base class, for that matter.

Dima
More than "lack of multiple inheritance" I would say, to replace multiple inheritance. Java was designed like this from the beginning because multiple inheritance create more problems than what it solves. Good answer
OscarRyz
Oscar, that depends on whether you are a C++ programmer who learned Java or vice versa. :) IMHO, if used judiciously, like almost anything in C++, multiple inheritance solves problems. An "interface" abstract base class is an example of a very judicious use of multiple inheritance.
Dima
A: 

A little addition to what's written up there:

First, make sure your destructor is also pure virtual

Second, you may want to inherit virtually (rather than normally) when you do implement, just for good measures.

Uri
Why inherit virtually?
Tim
I like virtual inheritance because conceptually it means that there is only one instance of the inherited class. Admittedly, the class here does not have any space requirement so it may be superfluous. I haven't done MI in C++ for a while, but wouldn't nonvirtual inheritance complicate upcasting?
Uri
Why, oh why, would anyone want to make the dtor in this case pure virtual? What would be the gain of that? You'd just force something onto the derived classes that they likely have no need to include - a dtor.
Johann Gerell
If there is a situation that an object would be destroyed through a pointer to the interface, you should make sure that the destructor is virtual...
Uri
There is nothing wrong with a pure virtual destructor. It's not necessary, but there's nothing wrong with it. Implementing a destructor in a derived class is hardly a huge burden on the implementor of that class. See my answer below for why you'd do this.
Rodyland
+1  A: 

You can also consider contract classes implemented with the NVI (Non Virtual Interface Pattern). For instance:

struct Contract1 :: boost:noncopyable
{
    virtual ~Contract1();
    void f(Parameters p) {
        assert(checkFPreconditions(p)&&"Contract1::f, pre-condition failure");
        // + class invariants.
        do_f(p);
        // Check post-conditions + class invariants.
    }
    private:
        virtual void do_f(Parameters p) = 0;
};
...
class Concrete : public Contract1, public Contract2
{
    private:
        virtual void do_f(Parameters p); // From contract 1.
        virtual void do_g(Parameters p); // From contract 2.
};
Luc Hermitte
+1  A: 

My answer is basically the same than others but I think there is two other important things to do:

  • declare a virtual destructor in your interface or make a protected non virtual one to avoid undefined behaviours if someone try to delete an objet of type "IDemo".
  • Use virtual inheritance to avoid problems whith multiple inheritance. (There is more often multiple inheritance when we us interfaces)

And like other answers:

  • Make a class with pure virtual methods.
  • Use the interface by creating another class that overrides those virtual methods.

    class IDemo { public: virtual void OverrideMe() = 0; virtual ~IDemo() {} }

Or

class IDemo
{
    public:
        virtual void OverrideMe() = 0;
    protected:
        ~IDemo() {}
}

And

class Child : virtual public IDemo
{
    public:
        virtual void OverrideMe()
        {
            //do stuff
        }
}
Rexxar
A: 

All good answers above. One extra thing you should keep in mind - you can also have a pure virtual destructor. The only difference is that you still need to implement it.

Confused?


    --- header file ----
    class foo {
    public:
      foo() {;}
      virtual ~foo() = 0;

      virtual bool overrideMe() {return false;}
    };

    ---- source ----
    foo::~foo()
    {
    }

The main reason you'd want to do this is if you want to provide interface methods, as I have, but make overriding them optional.

To make the class an interface class requires a pure virtual method, but all of your virtual methods have default implementations, so the only method left to make pure virtual is the destructor.

Reimplementing a destructor in the derived class is no big deal at all - I always reimplement a destructor, virtual or not, in my derived classes.

Rodyland
Why, oh why, would anyone want to make the dtor in this case pure virtual? What would be the gain of that? You'd just force something onto the derived classes that they likely have no need to include - a dtor.
Johann Gerell
Updated my answer to answer your question. Pure virtual destructor is a valid way to achieve (the only way to achieve?) an interface class where all methods have default implementations.
Rodyland
A: 

If you're on Windows then you could do the following:

struct __declspec(novtable) IFoo
{
    virtual void Bar();
};

class Child : public IFoo
{
    public:
        virtual void Bar() { /* Do Something */ }
}

I like this approach because it results in a lot smaller interface code and the generated code size can be significantly smaller. The use of novtable removes all reference to the vtable pointer in that class, so you can never instantiate it directly. See the documentation here - novtable.

Mark Ingram