4

Here's what I mean. I have a class hierarchy:

class A {
   virtual int f() = 0;
};

class B : public A {
   int f() override {return 5;}
   void doSpecificStuff() {}
}

B is a self-sufficient class that can be used on its own. But it also has many descendants:

class C : public B {
   int f() override {return 171;}
}

Is there any way to make sure that I won't forget to re-implement f when subclassing B?

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
Violet Giraffe
  • 32,368
  • 48
  • 194
  • 335
  • The only way I know is to make the method pure virtual. However, in case the method is only virtual, I wouldnt know how to do it. Do you really need `C` inheriting from `B` and not from `A` ? – 463035818_is_not_an_ai Jun 30 '15 at 13:12
  • I mean, thats the whole point of inheriting from a base class. If you do not want `C` to inherit `B`s implementation, you have to make it inherit directly from `A` (and in this case it is ensured that `C` has to provide its own implementation) – 463035818_is_not_an_ai Jun 30 '15 at 13:14
  • 1
    That's what [pure virtual methods with implementations](http://stackoverflow.com/questions/2089083/pure-virtual-function-with-implementation) are for. – Quentin Jun 30 '15 at 13:14
  • There are ways to [check if a member function exists](http://stackoverflow.com/q/87372/440558) using SFINAE, you could use such a solution together with [`static_assert`](http://en.cppreference.com/w/cpp/language/static_assert) in the global scope to list all classes and the members they need. It's a manual list that needs to be updated every time classes or members are added or removed, there's no automatic way to enforce it. – Some programmer dude Jun 30 '15 at 13:16
  • 6
    Ah, I think I get it now: You want users to be able to instantiate objects of type `B`, but implementers of derived classes to override `B::f`. Still, I'm not sure if this isn't an xy problem: Why *must* the derived classes override `B::f`? (Can we solve this with CRTP instead)? Why can't there by a `class B2 : B` that implements `B::f` and users can create instances from? – dyp Jun 30 '15 at 13:17
  • @Quentin: isn't a class with a pure virtual method always an abstract class, regardless of having or not having an implementation for that method? – Violet Giraffe Jun 30 '15 at 13:18
  • @dyp: it is an xy problem, but I don't see any other possible solution. The `f` method returns the description of this class (a string). The description that `B` returns makes little to no sense for `B`'s derivatives. – Violet Giraffe Jun 30 '15 at 13:20
  • @VioletGiraffe good point. – Quentin Jun 30 '15 at 13:20
  • @VioletGiraffe: Clearly the issue here is in using hand-rolled RTTI instead of real rtti ;p – Puppy Jun 30 '15 at 13:49
  • 1
    @Puppy: It has no relation to RTTI. – Violet Giraffe Jun 30 '15 at 13:49

1 Answers1

5

This solution is inspired by @dyp's comment:

You could split the two responsibilities of B, namely "provides B-style implementation" and "can be instantiated."

class B_for_implementation : public A
{
  void doSpecificStuff();
};

class B_for_objects final : public B_for_implementation
{
  int f() override {return 5;}
};

class C final : public B_for_implementation
{
  int f() override {return 171;}
};

Self-contained objects would be created from B_for_objects, while other classes would derive from B_for_implementation.

Violet Giraffe
  • 32,368
  • 48
  • 194
  • 335
Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • then such self-contained `B` objects won't provide the actual functionality that `B` class was created for (`doSpecificStuff`). Is there something missing from your code? – Violet Giraffe Jun 30 '15 at 13:48
  • Okay, this is viable. Thought of something similar myself, but couldn't refine the thought before I lost it :) – Violet Giraffe Jun 30 '15 at 13:50
  • 1
    This is the answer I was preparing. B remains abstract, and defines doSpecificStuff, but you add another derived class from B for "just plain B" – Kenny Ostrom Jun 30 '15 at 13:53
  • (not that it matters, but f returns void, hehe) – Kenny Ostrom Jun 30 '15 at 13:54
  • Is the `final` keyword standard C++? Never heard of it, and I do sort of follow the new C++ features. It's definitely not supported by MSVC 2013. There are `final` methods, but are there `final` classes? – Violet Giraffe Jun 30 '15 at 14:29
  • 1
    If you want `B_for_objects` to be final, I think the syntax is `class B_for_objects final : public B_for_implementation`. See http://en.cppreference.com/w/cpp/language/final – Suma Jun 30 '15 at 14:35
  • @Suma Thanks, I am rusty on C++11 stuff which VS2010 doesn't support (don't get much opportunity to use it elsewhere). I should have double-checked the syntax. – Angew is no longer proud of SO Jun 30 '15 at 15:13