почему дочерняя функция не вызывается при наследовании синглтона в С++

avatar
Sourav
9 августа 2021 в 03:39
40
1
0

У меня есть следующий тестовый код. Здесь вывод «от родителя», как я могу вызвать дочернюю функцию? Почему дочерняя функция не вызывается? рекомендуется наследовать от синглтона?

#include <iostream>
using namespace std;

class Singleton
{
    public:
    static Singleton& getInstance()
    {
        static Singleton s;
        return s; 
    }
    virtual void func()
    {
        cout << "from parent" << endl;
    }
};

class Child : public Singleton
{
    public:
    void func() override
    {
        cout << "from child" << endl;
    }
};
int main()
{
    Singleton& s = Child::getInstance();
    s.func();
}
Источник
JaMiT
9 августа 2021 в 03:44
1

Чтобы вызвать Child::func(), вам нужен объект типа Child (или, возможно, производный от него тип). Какая строка в вашем коде создает объект типа Child?

paddy
9 августа 2021 в 03:44
0

getInstance возвращает ссылку на объект Singleton, а не на объект Child.

Nathan Pierson
9 августа 2021 в 03:50
0

Я полагаю, что если бы вы хотели иметь синглтон с дочерними классами, не желая переписывать getInstance для каждого из них, вы могли бы использовать CRTP, но неясно, зачем вам это нужно. Что вы пытаетесь сделать с этим шаблоном?

Sourav
9 августа 2021 в 03:57
0

Привет @NathanPierson. Родительский класс используется для фактической реализации, а дочерний класс будет иметь некоторые конкретные фиктивные реализации для обхода некоторых операций. Дочерний элемент будет использоваться для тестирования определенных разделов родителя.

Ответы (1)

avatar
Nathan Pierson
9 августа 2021 в 04:11
0

Сейчас Singleton::getInstance всегда возвращает Singleton. Child не имеет собственной версии getInstance, поэтому Child::getInstance() разрешается вызовом Singleton::getInstance(), который возвращает Singleton, а не Child. Если мы используем CRTP, мы можем сделать так, чтобы Singleton::getInstance действительно знал производный тип, экземпляр которого мы пытаемся получить:

#include <iostream>
#include <type_traits>

template <class Derived>
class Singleton
{
public:
    static Derived& getInstance()
    {
        // Assert that the template arg really is derived from the appropriate instantiation of the base class template
        static_assert(std::is_base_of<Singleton<Derived>  Derived>::value);
        static Derived s;
        return s;
    }
    virtual void func()
    {
        std::cout << "from parent" << std::endl;
    }
};

class Child : public Singleton<Child>
{
public:
    void func() override
    {
        std::cout << "from child" << std::endl;
    }
};
int main()
{
    auto& s = Child::getInstance(); // s is a Child here
    s.func(); // Outputs "from child" as expected
}