0

I would like to have an abstract base class with the virtual method getInstance and some classes that inherit from it (all of them are singleton) to implement this method as static. The code would be something along the lines of this:

#include <iostream>
using namespace std;

class Father
{
public:
  virtual Father* getInstance();
protected:
  static Father* instance;
};

class Son : public Father
{
public:
  static Father* getInstance ()
  {
    if (instance == 0)
      instance = new Son();

    return instance;
  }

private:
  Son();
};


int main ()
{
  Father* son = Son::getInstance();
}

But the compiler won't let me override the getInstance method as static. Is there any other way to do this?

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
Cnoob
  • 169
  • 1
  • 3
  • 10
  • 3
    "all of them are singleton" - I'm so sorry. You are going to encounter so much pain down the road from the singleton *anti*-pattern. So easy to add, so many pitfalls and so devilishly hard to get rid of later. – Jesper Juhl Jun 03 '20 at 17:23
  • 1
    Does the compiler message "_`virtual` can only appear on non-static member functions_" give you an answer? – Ted Lyngmo Jun 03 '20 at 17:24
  • 3
    What are you trying to achieve? If you just remove `virtual` your code will work correctly – Alan Birtles Jun 03 '20 at 17:27
  • Why do you want to override anything at all? `virtual Father* getInstance();` requires an object to call on, which kind of defeats the purpose of this function. On the other hand the "overridden" `getInstance` of `Son` will always be called as `Son::getInstance()` as if `Father` doesn't even exist. – Lukas-T Jun 03 '20 at 17:35
  • Well, the purpose of declaring the method at Father class virtual is to "force" the classes that inherit from it to override it (as the method in the base class does nothing). I know I could just remove the virtual from the base class and get it working, but it seems like not using the resources of the language properly. – Cnoob Jun 03 '20 at 17:48
  • Is [this](https://godbolt.org/z/Tj7Pm3) similar to what you want? They are singletons with virtual methods. – Ted Lyngmo Jun 03 '20 at 17:54
  • This seems like a design problem. If the only derived class is `Son`, there's no problem: just merge all the code from `Father` into `Son` and get rid of `Father`. Assuming that that's not appropriate, what happens when someone calls `Son::getInstance()` and then calls `Daughter::getInstance()`? Will the pointer returned by `Daughter::getInstance()` point to a `Son` object? Does that make sense? – Pete Becker Jun 03 '20 at 17:59
  • It is more or less what I wrote above. It would work and it's very similar to what I want, but it doesn't force the classes that inherit from it to override the method. Guess I will do that, but I just was curious to know if there is another way. – Cnoob Jun 03 '20 at 18:00
  • @Cnoob Was that an answer to me+ – Ted Lyngmo Jun 03 '20 at 18:02
  • Note that the instance belongs to all the objects in this hierarchy, so `Something::getInstance()` will always return a pointer to the object that was created first. This does not seem like something anyone would want, ever. – molbdnilo Jun 03 '20 at 18:06
  • Unrelated: If you find that you absolutely MUST use singleton, [here's a much better singleton design](https://stackoverflow.com/a/1008289/4581301). – user4581301 Jun 03 '20 at 18:11
  • 1
    @TedLyngmo yes, I don't use Stack Overflow much and dont' really know how to answer comments or upvote them. It's just with the @ ? – Cnoob Jun 03 '20 at 18:33
  • @Cnoob Yes, that's it! – Ted Lyngmo Jun 03 '20 at 18:35
  • 1
    Okay, thank you very much @TedLyngmo! hahaha – Cnoob Jun 03 '20 at 18:36
  • @user4581301 I don't really see the difference with what I'm trying to do here (apart from the two methods implemented to avoid getting more copies of the object) – Cnoob Jun 03 '20 at 18:37
  • @PeteBecker yes, the idea is to have multiple classes all of which with it's own instance = new DerivedClass(). Wouldn't that return a pointer to the corresponding object? – Cnoob Jun 03 '20 at 18:39
  • One huge difference is the Meyers Singleton is inherently thread-safe in modern C++. If two threads hit the `if (instance == 0)` at the same time, the [Bad](https://en.cppreference.com/w/cpp/language/ub) will happen. Most of the time you won't notice, but there's this little window at start-up where the most likely effect is multiple leaked instantiations. Another one is the returned reference is a little bit safer than the returned pointer. Even if you stick with the dynamic allocation behind the scenes, you should consider returning a reference. – user4581301 Jun 03 '20 at 18:51
  • @Cnoob -- if **each** derived class is supposed to have its own singular instance, then **each** derived class has to have **its own** static pointer. As written, the first call to `getInstance()` would determine the instance that every subsequent call saw, regardless of the actual derived type. – Pete Becker Jun 03 '20 at 21:19
  • @PeteBecker owww, I thought they would inherit the attribute and have a copy each one, but what you said actually makes a lot of sense... thanks for the answer! – Cnoob Jun 04 '20 at 08:15
  • @JesperJuhl it looks like you have gone though a lot of pain with this pattern. I would love to hear why you think it is such a bad option. – Cnoob Jun 04 '20 at 08:17
  • @Cnoob In a nutshell; singletons are just glorified global variables and are bad for all the same reasons that regular globals are + more. You can end up with tightly coupled components (that shouldn't be) via the singleton. The initialization order is only well defined within the same translation unit, so if two singletons ever depend on eachother there's trouble ahead. Getting rid of a singleton once a ton of components depend on it is hard. Order of destruction is only defined within a translation unit. Global state that anyone can modify at any time makes debugging hard. And much more. – Jesper Juhl Jun 04 '20 at 14:19

0 Answers0