0

I have two classes of which one is a subclass of the other. The classes are layed out as a singleton. So the base class contains a static member which is set to the only instance of that class and can be refered to by a getter function (not relevant here, so I left it out). I now want to create the subclass in global context and save the instance to the static member variable. This is essentially what I have:

class LightBase
{
    protected:
        static LightBase instance_;
    // .. stuff
}

class NormalLight0_5 : public LightBase
{
    //.. other stuff
}

class NormalLight1_0 : public LightBase
{
    //.. other stuff
}

#ifdef CONFIG_LIGHT_TYPE_NORMAL0_5
NormalLight0_5 LightBase::instance_();  // <-- my attempt to instantiate a light of type 0.5
#elif
NormalLight1_0 LightBase::instance_();  // <-- my attempt to instantiate a light of type 1.0
#endif

But I get the following error:

error: no declaration matches 'NormalLight1_0 LightBase::instance_()'

What is the cause of this?

glades
  • 3,778
  • 1
  • 12
  • 34
  • 2
    the member is of type `LightBase` not of type `NormalLight1_0`. – 463035818_is_not_an_ai Jul 30 '21 at 10:07
  • Ahh so I guess if I want to instantiate the subclass It would have to be `NormalLight1_0 NormalLight1_0::instance_()`? – glades Jul 30 '21 at 11:17
  • no what i meant is that the member of `LightBase` is declared as `static LightBase instance_;`, it is not a `NormalLight1_0`. The matching definition would be `LightBase LightBase::instance_();`. I know thats not what you want, I just wanted to point out that already the decalration is off, while fixing the definition is secondary – 463035818_is_not_an_ai Jul 30 '21 at 11:22
  • @463035818_is_not_a_number ahh you see I want to use polymorphism here. So I should be able to instantiate the subclass dependent on some preprocessor macros, but stay general in my `instance_ definition`. I edited the question. Is this even doable then? – glades Jul 30 '21 at 11:25
  • "some preprocessor macros" ? no not at all. I'll try to write an answer... – 463035818_is_not_an_ai Jul 30 '21 at 11:26
  • how do you decide which subtype you want to instantiate? It is really decided at compile time already? If thats the case you don't need runtime polymorphism, but thats probably a topic for a different question – 463035818_is_not_an_ai Jul 30 '21 at 11:32
  • @463035818_is_not_a_number yes exactly. The type of light that gets instantiated is known at compile time. – glades Jul 30 '21 at 11:34
  • then most likely runtime polymorphism is the wrong tool. You are paying for something you don't use – 463035818_is_not_an_ai Jul 30 '21 at 11:35
  • My previous implementation featured an all #defines apprach and used only one class. But I wasn't happy and thought this would be a more elegant solution since i can pack up everything in a class. Is there a third approach? – glades Jul 30 '21 at 11:37
  • the term to search for is "compile time polymorphism". It is a broad topic, this is a nice q&a but it only scratches the surface https://stackoverflow.com/questions/1881468/what-is-compile-time-polymorphism-and-why-does-it-only-apply-to-functions – 463035818_is_not_an_ai Jul 30 '21 at 11:39
  • Thanks for pointing me into the right direction! I will have a look at that. – glades Jul 30 '21 at 11:44
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/235472/discussion-between-glades-and-463035818-is-not-a-number). – glades Jul 31 '21 at 07:00

1 Answers1

1

You need pointers or references for polymorphism. A LightBase member can only store a LightBase not one of its subclasses. Hence, it is not really the definition that is the problem, but rather your declaration is already off. In any case the definition must match the declaration.

You can use a std::unique_ptr:

#include <memory>

class LightBase {
    protected:
        static std::unique_ptr<LightBase> instance_;
};

class NormalLight1_0 : public LightBase {};

std::unique_ptr<LightBase> LightBase::instance_ = std::make_unique<NormalLight1_0>();
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185