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

Я хотел бы поставить следующий шаблон дизайна для обсуждения. Он реализует универсальный метод "getMany" в базовом классе, который использует данный метод get из производного класса для получения многих сущностей (здесь для упрощения явного типа int). Это означает, что любой производный класс должен сообщить методу getMany, какой метод get использовать. Это случай вызова функции указателя на член в производном классе из базового класса.

Что я хотел бы изложить в дискуссии: какие альтернативные, более легкие шаблоны для достижения того же вы можете придумать?

Спасибо!

PS: Как отмечалось выше, в реальном случае можно, конечно, абстрагировать фиксированный тип "int" к типу шаблона TPPS: предопределение get-методов как виртуальных методов в базовом классе не кажется хорошим вариантом, так как это ограничит количество и наименование get-методов.

#include <iostream>
#include <memory>
#include <algorithm>
#include <vector>

using namespace std;

// EXAMPLE FOR CALL VIA POINTER TO OVERLOADED METHOD IN DERIVED CLASS FROM BASE CLASS

class FooBase
{
    public:

    template<class PCLASS>
    std::vector<int> getMany(int (PCLASS::*getEnt)(int) const, int n, const PCLASS *pClass) const
    {
        std::vector<int> e;
        int i = 0;
        e.resize(n);

        for (std::vector<int>::iterator it = e.begin(); it!=e.end(); ++it) {
            *it = (pClass->*getEnt)( i++ );
        }

        return e;   
    };
};


class Foo : public FooBase 
{
    public:

    int Moo(int a) const
    {
        return a;
    };

    int Moo(char a) const
    {
        return (int)a;
    };

    std::vector<int> Moos(int n) const
    {
        int (Foo::*f)(int)const;
        f = &Foo::Moo;

        return getMany<Foo>(f, n, this);
    };

};

int main(int argc, char **args) 
{
    Foo* myFoo = new Foo();
    std::vector<int> res = myFoo->Moos(10);

    for (std::vector<int>::iterator it = res.begin(); it!=res.end(); ++it) {    
        std::cout << *it;
    }

    return 1;
}

2 ответа

Решение

Вот пример использования функциональных объектов.

class FooBase
{
public:
    template< typename FunctorType >
    std::vector<int> getMany(FunctorType const & functor, int n)
    {
        std::vector<int> e;
        int i = 0;
        e.resize(n);

        for (std::vector<int>::iterator it = e.begin(); it!=e.end(); ++it) {
            *it = functor( i++ );
        }
    }
};

При этом клиентский код может вызывать getMany с помощью lambdas (C++11) или создавать свои собственные объекты функций.

auto callMoo = [this] (char i) { return Moo(i); };
getMany(callMoo, n);

Вы можете просто использовать обычный полиморфизм здесь. Есть абстрактный метод, который вы вызываете через this указатель от метода базового класса. Упрощенный пример:

class FooBase
{
public:
    virtual void abstractCall() = 0; // pure virtual function, could make protected if you wanted
    void baseMethod()
    {
        this->abstractCall();  // MUST use the this pointer, not a "." call
    }
};

class FooDerived : public FooBase
{
public:
    virtual void abstractCall()
    {
        cout << "my concrete call!" << endl;
    }
};

void bar()
{
    FooDerived test;
    test.baseMethod();
}

Я надеюсь, что это дает вам основную идею.

Другие вопросы по тегам