0

In C++, is it possible to require a method in a base class to be overridden by all of its derived classes without making it a pure virtual method?

#include <iostream>
using namespace std;

class BaseClass{
    public:
    int printStuff(){ //find some way to require all derived classes to override this method
        cout << "Printing some stuff";
    }
};

class DerivedClass: public BaseClass{

};

int main(){
    cout << "Hello World!";
    return 0;
}
Kara
  • 6,115
  • 16
  • 50
  • 57
Anderson Green
  • 30,230
  • 67
  • 195
  • 328
  • 3
    Why wouldn't you use something that's designed to do this? – chris Jun 16 '12 at 19:38
  • You might need to have some more specifics. Because this question is really just asking "How do I do X? I don't want to do X." I assume you also want to give the method an implementation (which, by the way, you *can* do, even with pure virtual functions), but you haven't said that. – John Calsbeek Jun 16 '12 at 19:39
  • @JohnCalsbeek He wants to have a default implementation for that method. He wants a BaseClass that he can instantiate. But he would like to force derived classes to reimplement that method. Do I understand correctly? – Notinlist Jun 16 '12 at 19:57
  • 1
    You can do it without `virtual` with a SFINAE trick and some CRTP: http://stackoverflow.com/a/264088/168175 - just add a `static_assert` to that and you're done – Flexo Jun 16 '12 at 20:49
  • @chris I'm confused: what, specifically, is designed to do this? – Anderson Green Mar 10 '13 at 21:37
  • @AndersonGreen, It took me a second to remember (this being 10 months ago), but what I meant was that this is what pure virtual functions are there for. This wasn't written when you posted, but http://blogs.msdn.com/b/oldnewthing/archive/2013/02/06/10391383.aspx – chris Mar 10 '13 at 22:04

2 Answers2

4

I know you said you didn't want to use pure virtual functions, but you can use pure virtual functions and still give the method a definition if that's what you are trying to do (not sure if you knew that already):

class BaseClass{
public:
    virtual int printStuff() = 0;
};

// give the pure virtual function an implementation
int BaseClass::printStuff() {
    cout << "Printing some stuff";
}

class DerivedClass: public BaseClass{
    // compiler error; DerivedClass must override printStuff
};

class DerivedClass2: public BaseClass{
public:
    int printStuff() {
        return BaseClass::printStuff(); // use the base class's implementation
    }
};
Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
  • `BaseClass` fails to compile. – Notinlist Jun 16 '12 at 19:41
  • Still have problems: http://codepad.org/DKLTnxlu `DerivedClass` do compile, just cannot be instantiated. `BaseClass` now compiles, but cannot be instantiated. – Notinlist Jun 16 '12 at 19:51
  • @Notinlist That's exactly the expected behaviour. You're only supposed to be able to instantiate a `DerivedClass2`. – Seth Carnegie Jun 16 '12 at 19:53
  • What is the point in giving an implementation to `int BaseClass::printStuff()`? If we are not doing that then we are against the will of the questioner, namely "without making it a pure virtual method". – Notinlist Jun 16 '12 at 19:54
  • 1
    @Notinlist he didn't say why he didn't want to make it a pure virtual method so we can't assume it's because he wants to instantiate the base class. The point of giving an implementation to `BaseClass::printStuff` is to force explicit acceptance of the default by subclasses. – Seth Carnegie Jun 16 '12 at 19:57
0

It depends on what you mean by require. Usually "require" would mean "fails to compile unless it is done". If that is what you want, then pure virtual is the only want to define the method to achieve that. If you mean, "program won't work unless it is done", then you can provide a default implementation for a virtual method that does gives notice to the user that the implementation is missing.

class BaseClass {
protected:
    virtual int printStuff () {
        std::cout << "Nothing to print, please override printStuff()."
                  << std::endl;
        return -1;
    }
};

When an implementation for a virtual method is provided (that is, the virtual method is not declared with an assignment of 0), it is no longer "pure". So this technique satisfies your "not a pure virtual method" requirement, but it is still a virtual method.

I am assuming you want this because you believe some part of your code needs to instantiate a plain BaseClass. If that is the case, you may consider partitioning BaseClass into two parts. One that is the "pure" interface, the other that has the stuff you are actually going to use when you instantiate it.

class BaseObject {
    //...
};

class BaseClass {
protected:
    BaseObject base;
    virtual int printStuff () = 0;
};

So you would instantiate a BaseObject rather than a BaseClass.

jxh
  • 69,070
  • 8
  • 110
  • 193
  • By "require", I mean "does not compile if a certain condition is not met" or "exits the program and prints an error message if the condition is not met." Either of these solutions would be suitable for my purposes. – Anderson Green Jun 17 '12 at 22:34