56

I have a class which is to listen to mouse events. However, I do not want to force the user to implement any specific one, but I do want to make it clear that they must inherit it.

Is there a way to do this?

Thanks

jmasterx
  • 52,639
  • 96
  • 311
  • 557
  • 1
    Funny: Java's MouseAdapter is exactly what you're planning to write: an abstract class without any pure virtual methods so that people can choose freely which of the listener methods they want to implement and which not. – Michael Borgwardt Jan 09 '11 at 18:41
  • 2
    Does it actually matter if someone creates an instance of the base class and registers it as a mouse listener? Presumably it will just ignore everything (or do default actions for everything), exactly the same as if they'd bothered to type out the code to inherit from your class but implement none of the functions. Two different ways of doing something pointless instead of one. – Steve Jessop Jan 09 '11 at 19:39

5 Answers5

72

You can declare a pure virtual destructor, but give it a definition. The class will be abstract, but any inheriting classes will not by default be abstract.

struct Abstract
{
     virtual ~Abstract() = 0;
};

Abstract::~Abstract() {}

struct Valid: public Abstract
{
        // Notice you don't need to actually overide the base
        // classes pure virtual method as it has a default
};


int main()
{
    // Abstract        a;  // This line fails to compile as Abstract is abstract
    Valid           v;  // This compiles fine.
}
AbdullahC
  • 6,649
  • 3
  • 27
  • 43
Philip Potter
  • 8,975
  • 2
  • 37
  • 47
  • 2
    Can you give an example, I tried this but my subclasses still become abstract. – jmasterx Jan 09 '11 at 18:47
  • @Milo http://programmers.stackexchange.com/questions/35038/what-can-i-do-when-the-interviewer-doesnt-know-the-answer-to-his-her-own-questio/35043#35043 – Philip Potter Jan 09 '11 at 18:50
  • @Philip: Incorrect. The inheriting class will need to provide an implementation, otherwise they will still be abstract. – AbdullahC Jan 09 '11 at 19:06
  • @Martin: Philip says "pure virtual method". My point is that if you do it for the destructor, it's valid (because you don't override destructors anyway), but incorrect for any method in general. – AbdullahC Jan 09 '11 at 19:20
  • 1
    Hippo is correct here, although Hippo should have explicitly stated that in his former comment to avoid the confusion. – jmasterx Jan 09 '11 at 19:26
  • @Milo: Thanks, I've changed the post to make it "destructor" instead of "method". – AbdullahC Jan 11 '11 at 01:46
62

Specify the constructor of the base as protected. This does mean that you cannot construct it directly, but forces inheritance. There is nothing that makes a developer inherit from that class aside from good documentation though!

Example:

struct Abstract {
protected:
    Abstract() {}
};

struct Valid: public Abstract {
    // No need to override anything.
};


int main() {
    // Abstract a;  // This line fails constructor is protected
    Valid v;  // This compiles fine.
}
Ajay
  • 18,086
  • 12
  • 59
  • 105
Nim
  • 33,299
  • 2
  • 62
  • 101
  • 2
    This solution makes more sense to me than the virtual destructor, as you're explicitly restricting access to the constructor. I feel like this explains itself better than a virtual destructor. – John Leuenhagen Mar 11 '20 at 02:13
7

You can declare your base class as having a pure virtual destructor that you implement. Since a destructor is always provided by the compiler, the derived class won't be purely virtual, but the base class can't directly be instantiated. You should always declare a destructor as virtual anyway, so this will have no overhead.

class Base
{
public:
    virtual ~Base() = 0;
    virtual void SomeVirtualMethod();
};

inline Base::~Base()
{
}

class Derived : public Base
{
};

inline Base* createBase()
{
    // return new Base; // <- This won't compile
    return new Derived; // <- This does compile, Derived is not a pure virtual class !
}
Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Sylvain Defresne
  • 42,429
  • 12
  • 75
  • 85
1

Why would you want the user to inherit, if he does not have to implement anything.

When the base class is needed to be able to put all the "eventhandlers" in a std::set. Then no one can create a class and put it in this set without subclassing your base class. Because the set will be defined as

std::set<MyBaseClass*> mySet;
  • 1
    Maybe the user isn't inheriting, but two distinct classes offering exclusive members while having a common base makes sense. HttpTransaction->HttpRequest, HttpTransaction->HttpResponse, etc. –  Nov 03 '15 at 06:55
1

By definition, an abstract class is a class which has at least one pure virtual function. For your purpose, you can define the destructor to be pure virtual, and provide an implementation:

class abstract { 
        virtual ~abstract()=0; 
}; 

abstract::~abstract() {} 

By default, all inheriting classes will not be abstract, even though they will not need to implement any method.

AbdullahC
  • 6,649
  • 3
  • 27
  • 43