828

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

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Aaron Fischer
  • 19,913
  • 17
  • 69
  • 108

16 Answers16

711

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 concrete derived 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
        }
};

You don't have to include a body for the virtual destructor - it turns out some compilers have trouble optimizing an empty destructor and you're better off using the default.

Community
  • 1
  • 1
Mark Ransom
  • 271,357
  • 39
  • 345
  • 578
  • 110
    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 Nov 25 '08 at 17:52
  • 35
    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 Nov 25 '08 at 19:06
  • 4
    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 Jul 17 '09 at 14:28
  • 10
    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 Dec 31 '09 at 09:04
  • 4
    Forty moons ago, but anyway - @Mark Ransom, you wrote: "This allows you to pass pointer ownership to another party without exposing the base class." Did you mean "sub class"? Because then in your comment you wrote: "If you know you're not going to delete the class through a base class, you don't need the virtual destructor." - Sorry if my remark doesn't make sense - I'm a C++ noob and trying to learn from these questions and answers. – Lumi Mar 10 '12 at 21:40
  • 2
    @Lumi, now that I think about it you're absolutely correct. The interface is a base class because the concrete class derives from it and implements the methods. I should fix this. Give yourself a gold star for being the first to notice, I'm sure this answer has been viewed a thousand times. – Mark Ransom Mar 10 '12 at 22:42
  • @MarkRansom, thanks for the virtual gold star. :) Meanwhile, I figured out you must have meant what I surmised you had meant because I got to the bottom of the page where [Carlos' answer](http://stackoverflow.com/a/9571456/269126#9571456) makes the point clear with a code sample. Thanks for your feedback after such a long time! -- Best, Michael – Lumi Mar 10 '12 at 22:49
  • @PavelMinaev "_With a virtual destructor with a body, said destructor can be called (virtually) e.g. in the middle of construction_" seriously? – curiousguy Aug 16 '12 at 03:26
  • @curiousguy, yes you can call a destructor in the middle of construction when you `throw` from the constructor of a derived class. – Mark Ransom Aug 16 '12 at 03:31
  • Consider an inheritance hierarchy: `Base` – Pavel Minaev Aug 16 '12 at 18:24
  • 1
    @PavelMinaev, wouldn't it be UB to destroy an object explicitly before it's finished constructing? I can see the `MostDerived` constructor getting very unhappy. At least with destroying via `throw` the remainder of the construction is bypassed. – Mark Ransom Aug 16 '12 at 19:18
  • It would certainly be UB by the time it gets to the ctor of `MostDerived`, but I don't see anything that would make e.g. `this->~Foo()` in a ctor UB all by itself. Consider the case where you destruct it, and then never return to the ctor (e.g. just sit there in an infinite loop, taking and processing input). Inside that loop, your behavior would be well-defined, so far as I can see. – Pavel Minaev Aug 17 '12 at 00:01
  • 55
    How typical of a C++ answer that the top answer doesn't directly answer the question (though obviously the code is perfect), instead it optimizes the simple answer. – Tim Aug 24 '12 at 22:49
  • 19
    Don't forget that in C++11 you can specify the `override` keyword to allow for compile-time argument and return value type checking. For example, in the declaration of Child `virtual void OverrideMe() override;` – Sean Jan 15 '13 at 03:19
  • @Sean, this answer predates C++11 by a few years, but you make a good point - thanks! – Mark Ransom Jan 15 '13 at 03:42
  • I agree with @PavelMinaev, there is little if any reason for the destructor to be non-pure virtual. – Maxim Egorushkin Jan 16 '13 at 07:29
  • 1
    Also note that GCC cannot handle pure-virtual destructors and you need to define them: http://stackoverflow.com/a/3065223/447490 – Chris May 22 '13 at 04:29
  • @Chris I'm a little bit confused now regarding Mark Ransoms note on compiler optimization and your comment. Sounds like the former suggests using pure virtual destructors while the latter forbids it. Did I misunderstand something? If not, is there a general solution for this or is it compiler dependent? – Griddo Mar 12 '14 at 08:43
  • 4
    @Griddo No, you understand quite right. Mark Ransom suggests not defining the virtual destructor while GCC requires you to do so. I don't really think there is a general solution for this other than clutter your code with #ifdef and compiler checks but in this case I'd rather just go with defining it and maybe lose some optimization benefits on some compilers. – Chris Mar 12 '14 at 09:57
  • @xan Can you please explain the reasoning behind wanting to make the assignment operator and copy constructor pure virtual in the IDemo class. – Zachary Kraus Dec 09 '14 at 22:49
  • 1
    @ZacharyKraus an interface should be a very small subset of the class that actually implements the interface; in particular it won't have any data members. That almost guarantees that the compiler-generated copy and assignment operators will do the wrong thing. If you want to implement them yourself then knock yourself out, but it's usually not necessary - you access an interface via a pointer, and copies of the pointer are OK as long as you've handled ownership. – Mark Ransom Dec 10 '14 at 00:01
  • 3
    @ZacharyKraus: What MarkRansom said. If you are declaring an interface in this way, it's highly unlikely that the compiler's auto-generated attempts at these would be correct. Thus, it's safer to explicitly declare them pure virtual yourself and make sure that you can't accidental fall into the trap of using them. – xan Dec 10 '14 at 16:57
  • @MarkRansom I now understand the reasoning but I still have 2 questions that I just don't understand. The first is does the compiler automatically create the assignment and copy constructor for ever class even if you never use them in your code. Second, can you accidentally trigger either assignment or copy constructor when the object is a pointer? – Zachary Kraus Dec 17 '14 at 00:28
  • @ZacharyKraus their presence or absence isn't detectable unless you call them, so by the "as-if" rule it could go either way - I suspect most compilers don't. You can generate a call with e.g. `*a = *b` but I grant you it's not common. – Mark Ransom Dec 17 '14 at 02:23
  • Also, it simply daoesn't actually matter, as assinging / copying the interface doesn't *do* anything. – Deduplicator Jan 07 '16 at 19:28
  • Inside `Child` , is it still necessary to write `OverrideMe()` as `virtual void` ? – Sparker0i Aug 10 '18 at 18:57
  • 2
    @Sparker0i `virtual` is not necessary since the base class declaration already made it virtual, but it's good practice to be consistent. `void` is still necessary. – Mark Ransom Aug 10 '18 at 20:18
  • It would be nice if you mention that the destructor can be made pure virtual if no other function is available. – L. F. Jun 15 '19 at 13:15
  • What one should do with the warning that IDemo "has no out-of-line virtual method definitions"? – Glinka Jun 26 '19 at 14:40
  • To add to what @xan said, as of C++11 I presume you may also want to include a pure virtual declaration of the move constructor (and move assignment operator if not using the copy-and-swap idiom). – gblomqvist Mar 24 '21 at 19:23
  • 1
    @gblomqvist it might be even better to delete those methods entirely. It's hard to imagine a case where you would use an interface pointer to do an object move. – Mark Ransom Mar 24 '21 at 20:41
  • @MarkRansom That's a good point. – gblomqvist Mar 24 '21 at 22:13
250

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 ~IDemo() {}
        virtual void OverrideMe() = 0;
};

class Child : public IDemo
{
    public:
        virtual void OverrideMe()
        {
            //do stuff
        }
};
Warty
  • 6,709
  • 1
  • 26
  • 47
bradtgmurray
  • 12,395
  • 9
  • 33
  • 36
  • 31
    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 Nov 26 '08 at 08:33
  • 12
    Why is the OverrideMe method in Child class is virtual ? Is that necessary ? – Cemre Mengü Jan 31 '12 at 22:26
  • 9
    @Cemre - no it's not necessary, but it doesn't hurt either. – PowerApp101 Feb 12 '12 at 11:15
  • 11
    It is generally a good idea to keep the keyword 'virtual' whenever overriding a virtual method. Though not required, it can make the code clearer - otherwise, you have no indication that that method could be used polymorphically, or even exists in the base class. – Kevin Oct 03 '14 at 20:47
  • 28
    @Kevin Except with `override` in C++11 – keyser Nov 26 '14 at 21:34
  • 4
    Don't forget the semicolons at the end of the class declarations. – Phylliida Oct 14 '15 at 16:40
  • 1
    It's not necessary to declare `Child::OverrideMe()` as `virtual`, @Cemre, because `IDemo::OverrideMe()` makes `Child::OverrideMe()` implicitly `virtual`. Having an indication that it's a virtual function (such as `virtual`, or better yet, `override` in C++11 or later) will serve as a reminder for programmers, with `override` in particular also helping the compiler check that it does indeed override something. – Justin Time - Reinstate Monica Jul 28 '19 at 16:41
157

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.

Raedwald
  • 40,290
  • 35
  • 127
  • 207
Joel Coehoorn
  • 362,140
  • 107
  • 528
  • 764
  • 19
    It would still be nice to be able to create interfaces, to save us from typing so much (virtual , =0, virtual destructor). Also multiple inheritance seems like a really bad idea to me and I've never seen it used in practice, but interfaces are needed all the time. To bad the C++ comity won't introduce interfaces just because I want them. –  Aug 01 '12 at 06:05
  • 10
    Ha11owed: It has interfaces. They're called classes with pure virtual methods and no method implementations. – Miles Rout Jan 01 '13 at 06:51
  • @Ha11owed There are some quirks in Java caused by lack of multiple inheritance. Take a look at `java.lang.Thread` class and `java.lang.Runnable` interface, which exists just because you can not extend `Thread` along with another base. From documentation it may seem that it's provided for your choice, but I was once forced to use `Runnable` because of lack of multiple inheritance. – doc Oct 15 '14 at 16:50
  • 1
    @MilesRout: I know, but still, why force me write so much boilerplate code? Also it would be clear that you are looking at an interface without having to scan all methods and check that they are all pure virtual. –  Nov 28 '14 at 15:04
  • 7
    @doc: java.lang.Thread has methods and constants that you probably don't want to have in your object. What should the compiler do if you extend from Thread, and another class with the public method checkAccess()? Would you really prefer to use strongly named base pointers like in C++? This seems like bad design, you usually need composition where you think that you need multiple inheritance. –  Nov 28 '14 at 15:05
  • 4
    @Ha11owed it was long time ago so I don't remember details, but it had methods and contants that I wanted to have in my class and more importantly I wanted my derived class object to be a `Thread` instance. Multiple inheritance can be bad design as well as composition. It all depends on case. – doc Nov 28 '14 at 15:21
  • 1
    @Ha11owed +1 for "you usually need composition where you think that you need multiple inheritance" – Joel Coehoorn Nov 30 '14 at 03:49
  • There is no `abstract` keyword in C++. – Don Larynx Mar 24 '15 at 04:19
  • "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." - The assertion that this is the reason is completely false. Interfaces exist in Java so as not to conflate the concepts of conformation to a contract and shared implementation. This is a common misconception among C++ developers attempting to disparage what is arguably a design more consistent with pure OO languages. – Dave Dec 16 '15 at 05:53
  • Objective-C also supports this via Protocols and goes a step further (confusingly at first) by making Protocol method implementation optional. This has provided Objective-C with much of what C++ will soon get via Concepts. – Dave Dec 16 '15 at 05:55
  • 2
    @Dave: Really? Objective-C has compile-time evaluation, and templates? – Deduplicator Jan 07 '16 at 18:32
  • @Deduplicator - I'm referring to the key property of concepts being that they allow a callee (in your case a template) to specify constraints on the API that an argument must/should support where those constraints are expressed within the declaration or definition of the callee rather than within the class hierarchy of the argument. No Objective-C doesn't have templates. Templates in this discussion are the things being improved by a "concept" similar in some respects to Objective-C's protocols. But I'm sure you already knew that. – Dave Jan 23 '16 at 10:18
  • then give an example of what you call multiple inheritance, becos so far it seems java can do it but not c++, java can implment many interface – fdsfdsfdsfds Mar 29 '18 at 17:18
  • c++ can directly inherit from many classes. java can only directly inherit from one class. – Joel Coehoorn Mar 29 '18 at 17:23
56

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.

Morgoth
  • 4,139
  • 5
  • 35
  • 53
Dima
  • 37,098
  • 13
  • 69
  • 112
  • 13
    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 Nov 25 '08 at 17:32
  • 12
    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 Nov 25 '08 at 17:40
  • 10
    @OscarRyz Wrong. MI only creates problem when misused. Most alleged problems with MI would also come up with alternate designs (without MI). **When people have a problem with their design with MI, it's the fault of MI; if they have a design problem with SI, it's their own fault.** "Diamond of death" (repeated inheritance) is a prime example. MI bashing is not pure hypocrisy, but close. – curiousguy Aug 16 '12 at 03:24
  • 4
    Semantically, interfaces are different from abstract classes, so Java's interfaces are not just a technical workaround. The choice between defining an interface or an abstract class is driven by semantics, not technical considerations. Let's imagine some interface "HasEngine": that's an aspect, a feature, and it can be applied to / implemented by very different types (whether classes or abstract classes), so we'll define an interface for that, not an abstract class. – Marek Stanley Mar 25 '15 at 17:22
  • 2
    @MarekStanley, you may be right, but I wish you'd picked a better example. I like to think of it in terms of inheriting an interface vs. inheriting an implementation. In C++ you can either inherit both interface and implementation together (public inheritance) or you can inherit only the implementation (private inheritance). In Java you have the option of inheriting just the interface, without an implementation. – Dima Mar 25 '15 at 17:28
  • @curiousguy That sums it up pretty well. Generally speaking, it's more difficult to use multiple inheritance properly than it is to use single inheritance properly, but merely being more difficult doesn't mean it's impossible. An example would be something like this: `class Button; class Image; class ClickableIcon : public Button, public Image {};` . If they're designed properly, Image will supply the graphics functionality and Button will supply the interactive functionality, with no overlap that could cause issues, while ClickableIcon itself handles the functionality the button is for. – Justin Time - Reinstate Monica Apr 08 '16 at 18:53
  • ...I could've worded that example _much_ better. `Button` provides the interactive code, `Image` provides the graphics code, and `ClickableIcon` provides code specific to itself, as well as any code needed to weld the two parent classes together. As long as the two classes are designed properly, and have no overlapping member names, the class should be entirely viable, and easier to implement than if one or both was an interface. – Justin Time - Reinstate Monica Apr 08 '16 at 19:32
44

As far I could test, it is very important to add the virtual destructor. I'm using objects created with new and destroyed with delete.

If you do not add the virtual destructor in the interface, then the destructor of the inherited class is not called.

class IBase {
public:
    virtual ~IBase() {}; // destructor, use it to call destructor of the inherit classes
    virtual void Describe() = 0; // pure virtual method
};

class Tester : public IBase {
public:
    Tester(std::string name);
    virtual ~Tester();
    virtual void Describe();
private:
    std::string privatename;
};

Tester::Tester(std::string name) {
    std::cout << "Tester constructor" << std::endl;
    this->privatename = name;
}

Tester::~Tester() {
    std::cout << "Tester destructor" << std::endl;
}

void Tester::Describe() {
    std::cout << "I'm Tester [" << this->privatename << "]" << std::endl;
}


void descriptor(IBase * obj) {
    obj->Describe();
}

int main(int argc, char** argv) {

    std::cout << std::endl << "Tester Testing..." << std::endl;
    Tester * obj1 = new Tester("Declared with Tester");
    descriptor(obj1);
    delete obj1;

    std::cout << std::endl << "IBase Testing..." << std::endl;
    IBase * obj2 = new Tester("Declared with IBase");
    descriptor(obj2);
    delete obj2;

    // this is a bad usage of the object since it is created with "new" but there are no "delete"
    std::cout << std::endl << "Tester not defined..." << std::endl;
    descriptor(new Tester("Not defined"));


    return 0;
}

If you run the previous code without virtual ~IBase() {};, you will see that the destructor Tester::~Tester() is never called.

Boris Dalstein
  • 5,395
  • 3
  • 26
  • 48
Carlos C Soto
  • 915
  • 7
  • 11
  • 3
    Best answer on this page as it makes the point by supplying a practical, compilable example. Cheers! – Lumi Mar 10 '12 at 22:43
  • 1
    Testet::~Tester() runs only when the obj is "Declared with Tester". – Alessandro L. Jan 17 '13 at 14:01
  • Actually, the string privatename's destructor will be called, and in memory, that is all there will be allocated for. As far as the runtime is concerned, when all the concrete members of a class are destroyed, so is the class instance. I tried a similar experiment with a Line class that had two Point structs and found both the structs were destructed (Ha!) upon a delete call or return from the encompassing function. valgrind confirmed 0 leak. – Chris Reid May 26 '17 at 07:46
32

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

  1. Declare a virtual destructor in your interface or make a protected non-virtual one to avoid undefined behaviours if someone tries to delete an object of type IDemo.

  2. Use virtual inheritance to avoid problems whith multiple inheritance. (There is more often multiple inheritance when we use 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
            }
    }
    
Jason Plank
  • 2,322
  • 4
  • 29
  • 39
Rexxar
  • 1,808
  • 1
  • 13
  • 19
  • 2
    there is no need for virtual inheritance as you do not have any data members in an interface. – Robocide Jul 03 '11 at 07:22
  • 3
    Virtual inheritance is important for methods as well. Without it, you will run into ambiguities with OverrideMe(), even if one of the 'instances' of it is pure virtual (just tried this myself). – Knarf Navillus Aug 01 '12 at 00:22
  • 6
    @Avishay_ "_there is no need for virtual inheritance as you do not have any data members in an interface._" Wrong. – curiousguy Aug 16 '12 at 03:25
  • Notice that virtual inheritance may not work on some gcc versions, as version 4.3.3 which is shipped with WinAVR 2010: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35067 – mMontu Sep 19 '12 at 17:55
  • -1 for having a non-virtual protected destructor, sorry – Wolf Mar 14 '14 at 11:06
11

In C++11 you can easily avoid inheritance altogether:

struct Interface {
  explicit Interface(SomeType& other)
  : foo([=](){ return other.my_foo(); }), 
    bar([=](){ return other.my_bar(); }), /*...*/ {}
  explicit Interface(SomeOtherType& other)
  : foo([=](){ return other.some_foo(); }), 
    bar([=](){ return other.some_bar(); }), /*...*/ {}
  // you can add more types here...

  // or use a generic constructor:
  template<class T>
  explicit Interface(T& other)
  : foo([=](){ return other.foo(); }), 
    bar([=](){ return other.bar(); }), /*...*/ {}

  const std::function<void(std::string)> foo;
  const std::function<void(std::string)> bar;
  // ...
};

In this case, an Interface has reference semantics, i.e. you have to make sure that the object outlives the interface (it is also possible to make interfaces with value semantics).

These type of interfaces have their pros and cons:

  • They require more memory than inheritance based polymorphism.
  • They are in general faster than inheritance based polymorphism.
  • In those cases in which you know the final type, they are much faster! (some compilers like gcc and clang perform more optimizations in types that do not have/inherit from types with virtual functions).

Finally, inheritance is the root of all evil in complex software design. In Sean Parent's Value Semantics and Concepts-based Polymorphism (highly recommended, better versions of this technique are explained there) the following case is studied:

Say I have an application in which I deal with my shapes polymorphically using the MyShape interface:

struct MyShape { virtual void my_draw() = 0; };
struct Circle : MyShape { void my_draw() { /* ... */ } };
// more shapes: e.g. triangle

In your application, you do the same with different shapes using the YourShape interface:

struct YourShape { virtual void your_draw() = 0; };
struct Square : YourShape { void your_draw() { /* ... */ } };
/// some more shapes here...

Now say you want to use some of the shapes that I've developed in your application. Conceptually, our shapes have the same interface, but to make my shapes work in your application you would need to extend my shapes as follows:

struct Circle : MyShape, YourShape { 
  void my_draw() { /*stays the same*/ };
  void your_draw() { my_draw(); }
};

First, modifying my shapes might not be possible at all. Furthermore, multiple inheritance leads the road to spaghetti code (imagine a third project comes in that is using the TheirShape interface... what happens if they also call their draw function my_draw ?).

Update: There are a couple of new references about non-inheritance based polymorphism:

Community
  • 1
  • 1
gnzlbg
  • 6,587
  • 3
  • 46
  • 94
  • 5
    TBH inheritance is far more clear than that C++11 thing, which pretends to be an interface, but is rather a glue to bind some inconsistent designs. Shapes example is detached from reality and `Circle` class is a poor design. You should use `Adapter` pattern in such cases. Sorry if it will sound a little bit harsh, but try to use some real life library like `Qt` before making judgements about inheritance. Inheritance makes life much easier. – doc Oct 15 '14 at 17:28
  • 2
    It doesn't sound harsh at all. How is the shape example detached from reality? Could you give an example (maybe on ideone) of fixing Circle using the `Adapter` pattern? I'm interested to see its advantages. – gnzlbg Oct 15 '14 at 17:42
  • O.K. I will try to fit in this tiny box. First of all, you usually choose libraries like "MyShape" before you start writing your own application, to safe your work. Otherwise how could you know `Square` isn't already there? Foreknowledge? That's why it is detached from reality. And in reality if you choose to rely on "MyShape" library you can adopt to its interface from the very beginning. In shapes example there are many nonsenses (one of which is that you have two `Circle` structs), but adapter would look something like that -> http://ideone.com/UogjWk – doc Oct 15 '14 at 18:18
  • As I mentioned Qt. Check this example -> http://qt-project.org/doc/qt-5/qtwidgets-widgets-scribble-example.html to see how robust inheritance altogether with virtual methods is. And with banned inheritance and that C++11 "interface" thing instead, am I supposed to implement every time ALL virtual methods that QWidget has? Would I need to delegate each call to check for example my custom widget position? On the other hand Qt must had become header only library, because of "interface" thing required to invoke my implementations. – doc Oct 15 '14 at 20:22
  • 2
    It is not detached from reality then. When company A buys company B and wants to integrate company B's codebase into A's, you have two completely independent code bases. Imagine each has a Shape hierarchy of different types. You cannot combine them easily with inheritance, and add company C and you have a huge mess. I think you should watch this talk: https://www.youtube.com/watch?v=0I0FD3N5cgM My answer is older, but you'll see the similarities. You don't have to reimplement everything all the time,you can provide an implementation in the interface, and choose a member function if available. – gnzlbg Oct 15 '14 at 21:56
  • There are also a couple of talks by Sean Parent about concept-based polymorphism that might be interesting to you. – gnzlbg Oct 15 '14 at 22:16
  • Mentioned Qt was owned by 3 companies (Trolltech, Nokia, Digia) but none of them did the thing you say. It is detached from reality. Give me an example of real world software where such code merging took place. Even if so you should use `Adapter` pattern. Providing implementation in interface like one in your answer means that I have to provide all virtual methods, which otherwise could be simply inherited. – doc Oct 16 '14 at 01:51
  • 1
    I've watched part of video and this is totally wrong. I never use dynamic_cast except for debugging purposes. Dynamic cast means theres something wrong with your design and designs in this video are wrong by design :). Guy even mentions Qt, but even here he is wrong - QLayout does not inherit from QWidget nor the other way around! – doc Oct 16 '14 at 02:19
  • I've updated the answer with reference in case you are interested into learning more about this. Those three companies you mention were all working using the same library. Inheritance becomes a huge problem when this is not the case. Examples of companies are shown in the Sean Parent talk about concept-based polymorphism.The links provided have more information than I can provide here. – gnzlbg Oct 16 '14 at 09:15
  • I've watched video on concept-based polymorphism. While the technique is interesting and may find some applications this can't replace inheritance based polymorphism (and this concept-based polymorphism still uses inheritance only hidden in private model structs). Polymorphism is not only for your internals, but also to provide a way application can interact with a library. Photoshop is not a library so it wasn't even considered in the video. I can't see any practical features in conecpt-based polymorphism that couldn't be achieved with IMO much cleaner inheritance. – doc Oct 16 '14 at 16:21
  • I agree that inheritance based polymorphism is very easy to use in C++ (this feature has full language support). In C for example it is very hard to do it. In Haskell, Rust, Scala.. you have traits and typeclasses which are kind of like language support for non-inheritance based polymorphism. I've used it in an app and was pretty happy with it. Mostly due to the performance boost it gave me (I can have vectors of each type, and a vector of interfaces, so I only use polymorphism where i really need it). We'll see how this evolves in C++, people have started talking about it fairly recently... – gnzlbg Oct 16 '14 at 19:06
  • 1
    Right. The problem is I can't see why inheritance is "the root of all evil". Such statement is ridiculous. – doc Oct 17 '14 at 02:58
  • Well the statement is more like "inheritance-based polymorphism is the root of all evil". After thinking a bit more about the solution you provided using the Adaptor pattern, the advantage I see about using a type-erased interface instead (like the one sean parent uses) is that your interface is in a single place, and you can extend its behavior and provide defaults via non-member non-friend functions. The interface is, however, way more complex to implement. The extension mechanism... its ADL vs not-ADL. If you go for ADL you are basically "stealing" function names from your users namespaces. – gnzlbg Oct 18 '14 at 08:39
  • And that's IMO bad, because you want to divide complex software into small logical pieces and inheritance helps you accomplish it. Having all kinds of objects (models in this specific case) degenerated to a single class is not convincing to me. How am I supposed to extend such concept-based interface if I don't have access to `object_t` internals nor I can't inherit after it? From what I see, I have to implement `draw()` function from scratch on my own and I am not binded to `concept_t` interface. Also, with virtual methods I can have default implementations, which I can override or not. – doc Oct 18 '14 at 15:06
  • Term "interface" comes from Java world. What Java doc has to say: "Implementing an interface allows a class to become **more formal about the behavior it promises to provide**. Interfaces form a contract between the class and the outside world, and this contract is **enforced** at build time by the compiler. If your class claims to implement an interface, all methods defined by that interface must appear in its source code before the class will successfully compile." (http://docs.oracle.com/javase/tutorial/java/concepts/interface.html) Thing you are presenting is like world upside down. – doc Oct 18 '14 at 15:59
  • Exactly, and I think that it is the correct thing to do: "write your class first, make it model an interface later". It completely decouples your class implementation from modeling a given interface, and allows you to use your class in context you couldn't had thought of at the moment of writing it. C++ concepts, haskell typeclasses, rust/scala traits, and the Adaptor pattern you showed work this way. This same reasoning is behind the NVI idiom, but these other solutions decouple the design even more, since a class is not an interface anymore (in the "is a" sense of inheritance). – gnzlbg Oct 18 '14 at 16:37
  • This is a road to pure mess. Adapter pattern exists to bind incompatible interfaces, if necessary, but interfaces which already exist. I don't know why even use classes with approach "write your class first". This asks to come back to pure C. On what premise are you building your class if you don't know how it will interact with outer world? Say you used your own implementation of `gnzlbg::vector` in your class and I provide interface with my custom `doc::vector` and you have to convert input and output to your internals. Where's our code re-use and efficiency if you need to convert them? – doc Oct 18 '14 at 16:58
  • Note first, that an interface can wrap a type either by value, unique reference, or shared reference. Second, this problem with vector already exist since allocator is in the std::vector type. The solution is either to convert (which involves copy: expensive), or provide an iterator interface instead using e.g. Boost.Iterator.any_iterator (which uses the type-erasure described here, and is slow). Why do you say it asks to come back to pure C? The interfaces are type-safe, and can be very thin. I build my classes knowing that my knowledge about my problem (and my needs) will change with time. – gnzlbg Oct 19 '14 at 09:38
  • What would be the inheritance based solution if you cannot modify my code? The best I can come up with is: have a pure virtual base class vector, make yours inherit from it (always pay vtable), make your vectors function virtual (always pay this price), and use Adaptor pattern for my vector. The alternative would be, create a vector interface that adapts your vector and my vector. And use the interface when you _need_ to polymorphically access your vector and my vector, but only in those places. And here when I say interface I mean mine, or one based on the adaptor pattern. – gnzlbg Oct 19 '14 at 09:46
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/63304/discussion-between-gnzlbg-and-doc). – gnzlbg Oct 19 '14 at 10:06
  • Wrapping type will not prevent you from reimplementing same functionality and doing very expensive conversion between vector types. Problem with vector does not exist if we both use either `doc::vector` or `gnzlbg::vector` on interface premise. You should learn how to properly use inheritance, because what you are saying now, does not make any sense! – doc Oct 19 '14 at 14:14
9

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
  • 508
  • 3
  • 11
  • 4
    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 Nov 26 '08 at 07:57
  • 6
    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 Dec 02 '08 at 20:27
7

If you're using Microsoft's C++ compiler, then you could do the following:

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

class Child : public IFoo
{
public:
    virtual void Bar() override { /* 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.

Cody Gray
  • 222,280
  • 47
  • 466
  • 543
Mark Ingram
  • 65,792
  • 48
  • 164
  • 225
  • 4
    I don't quite see why you used `novtable` over standard `virtual void Bar() = 0;` – Flexo Sep 17 '11 at 13:09
  • 2
    It's in addition to (I've just noticed the missing `= 0;` which I've added). Read the documentation if you don't understand it. – Mark Ingram Sep 20 '11 at 14:44
  • I read it without the `= 0;` and assumed it was just a non-standard way of doing exactly the same. – Flexo Sep 20 '11 at 14:47
6

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

struct Contract1 : boost::noncopyable
{
    virtual ~Contract1() = default;
    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:
    void do_f(Parameters p) override; // From contract 1.
    void do_g(Parameters p) override; // From contract 2.
};
Luc Hermitte
  • 29,719
  • 7
  • 60
  • 74
  • For other readers, this [Dr Dobbs article](http://drdobbs.com/cpp/184403760) "Conversations: Virtually Yours" by Jim Hyslop and Herb Sutter elaborates a bit more on why one might want to use the NVI. – user2067021 Nov 01 '11 at 00:39
  • And also [this article](http://www.gotw.ca/publications/mill18.htm) "Virtuality" by Herb Sutter. – user2067021 Nov 01 '11 at 01:15
4

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
  • 84,589
  • 46
  • 214
  • 312
  • 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 Nov 25 '08 at 19:09
  • 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 Nov 26 '08 at 07:55
  • 2
    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 Nov 26 '08 at 09:14
  • 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 Dec 05 '08 at 03:24
  • +1 for virtual inheritance, because with interfaces it is more likely that class will derive interface from two or more paths. I opt for protected destructors in interfaces tho. – doc Oct 17 '14 at 12:33
  • @JohannGerell I believe the intention behind pure virtual destructors is to prevent a vtable from being generated unless a class that inherits from your interface class is itself inherited from. If this is the intention, though, the destructor should be both declared pure virtual and defined, as so: `class Base { public: ~Base() = 0; }; Base::~Base() {}`, to allow the compiler to generate default constructors for derived classes – Justin Time - Reinstate Monica Apr 08 '16 at 20:14
1

I'm still new in C++ development. I started with Visual Studio (VS).

Yet, no one seems to mentioned the __interface in VS (.NET). I am not very sure if this is a good way to declare an interface. But it seems to provide an additional enforcement (mentioned in the documents). Such that you don't have to explicitly specify the virtual TYPE Method() = 0;, since it will be automatically converted.

__interface IMyInterface {
   HRESULT CommitX();
   HRESULT get_X(BSTR* pbstrName);
};

However, I don't use it because I am concern about the cross platform compilation compatibility, since it only available under .NET.

If anyone do have anything interesting about it, please share. :-)

Thanks.

Yeo
  • 9,853
  • 6
  • 57
  • 83
1

While it's true that virtual is the de-facto standard to define an interface, let's not forget about the classic C-like pattern, which comes with a constructor in C++:

struct IButton
{
    void (*click)(); // might be std::function(void()) if you prefer

    IButton( void (*click_)() )
    : click(click_)
    {
    }
};

// call as:
// (button.*click)();

This has the advantage that you can re-bind events runtime without having to construct your class again (as C++ does not have a syntax for changing polymorphic types, this is a workaround for chameleon classes).

Tips:

  • You might inherit from this as a base class (both virtual and non-virtual are permitted) and fill click in your descendant's constructor.
  • You might have the function pointer as a protected member and have a public reference and/or getter.
  • As mentioned above, this allows you to switch the implementation in runtime. Thus it's a way to manage state as well. Depending on the number of ifs vs. state changes in your code, this might be faster than switch()es or ifs (turnaround is expected around 3-4 ifs, but always measure first.
  • If you choose std::function<> over function pointers, you might be able to manage all your object data within IBase. From this point, you can have value schematics for IBase (e.g., std::vector<IBase> will work). Note that this might be slower depending on your compiler and STL code; also that current implementations of std::function<> tend to have an overhead when compared to function pointers or even virtual functions (this might change in the future).
lorro
  • 4,949
  • 15
  • 25
0

Here is the definition of abstract class in c++ standard

n4687

13.4.2

An abstract class is a class that can be used only as a base class of some other class; no objects of an abstract class can be created except as subobjects of a class derived from it. A class is abstract if it has at least one pure virtual function.

陳 力
  • 4,063
  • 1
  • 18
  • 41
0

In C++20, you can use a concept instead of a class. It is more efficient than inheritance.

template <class T>
concept MyInterface = requires (T t) {
    { t.interfaceMethod() };
};

class Implementation {
public:
    void interfaceMethod();
};
static_assert(MyInterface<Implementation>);

Then you can use it in a function:

void myFunction(MyInterface auto& arg);

The limitation is that you cannot use it in a container.

Nathan Xabedi
  • 1,060
  • 1
  • 7
  • 14
-2
class Shape 
{
public:
   // pure virtual function providing interface framework.
   virtual int getArea() = 0;
   void setWidth(int w)
   {
      width = w;
   }
   void setHeight(int h)
   {
      height = h;
   }
protected:
    int width;
    int height;
};

class Rectangle: public Shape
{
public:
    int getArea()
    { 
        return (width * height); 
    }
};
class Triangle: public Shape
{
public:
    int getArea()
    { 
        return (width * height)/2; 
    }
};

int main(void)
{
     Rectangle Rect;
     Triangle  Tri;

     Rect.setWidth(5);
     Rect.setHeight(7);

     cout << "Rectangle area: " << Rect.getArea() << endl;

     Tri.setWidth(5);
     Tri.setHeight(7);

     cout << "Triangle area: " << Tri.getArea() << endl; 

     return 0;
}

Result: Rectangle area: 35 Triangle area: 17

We have seen how an abstract class defined an interface in terms of getArea() and two other classes implemented same function but with different algorithm to calculate the area specific to the shape.

hims
  • 315
  • 3
  • 10
  • 5
    This is not what is considered an interface! That's just an abstract base class with one method that needs to be overridden! Interfaces are typically objects that contain only method definitions - a "contract" other classes have to fulfill when they implement the interface. – guitarflow Mar 26 '14 at 10:55