Наследование: функция, которая возвращает тип self?

Скажем, у меня есть два класса:

class A
{
    public:
    A* Hello()
    {
        return this;
    }
}

class B:public class A
{
    public:
    B* World()
    {
        return this;
    }
}

И пусть скажем, что у меня есть экземпляр класса B:

B test;

Если я вызываю test.World()->Hello(), это будет работать нормально. Но test.Hello()->World() не будет работать, поскольку Hello() возвращает A тип.

Как я могу сделать Hello() вернуть тип B? Я не хочу использовать функцию virtual, так как у нас есть более 20 разных классов, наследующих A.

Ответ 1

Вы можете использовать CRTP, любопытно повторяющийся шаблон шаблона:

template<class Derived>
class A
{
    public:
    Derived* Hello()
    {
        return static_cast<Derived*>(this);
    }
};

class B : public A<B>
{
    public:
    B* World()
    {
        return this;
    }
};


int main() {
    B test;
    test.World()->Hello();
    test.Hello()->World();
}

Ответ 2

У вас может быть еще один метод Hello в B, даже если он не виртуальный:

class A
{
    public:
    A* Hello() { return this; }
}

class B:public class A
{
    public:
    B* Hello() { return this; }
    B* World() { return this; }
}

Ответ 3

Нет необходимости делать Hello() return a B*. Hello() возвращает A*, и все, что вам нужно сделать, это указать A* на B*, чтобы позвонить test.Hello()->World(). Например:

B* b = dynamic_cast<B*>(test.Hello());
if(b != 0) b->World();