Может ли указатель одной функции указывать на функцию-член нескольких классов - PullRequest
3 голосов
/ 03 марта 2012

Вот требования, предъявляемые моим приложением. У меня есть класс A, который принимает указатель на функцию, скажем, cFunc. По сути, в моей реализации A он вызывал cFunc несколько раз.

Сам указатель cFunc должен указывать на различные функции в зависимости от приложения. Таким образом, для каждого приложения я создаю класс с тем же определением функции, что и cFunc, однако я не могу назначить функцию-член класса этому указателю

class A {
    typedef double (*Def_CFunc)(std::vector<double>);
    A(Def_CFunc _cFunc) { // Some implementation}
    // Other Functions
};

class B { double someFunc(std::vector<double> b); };
class C { double someOtherFunc(std::vector<double> a); };

int main () {
    B firstObj;
    C secondObj;

    // Depending upon the situation, I want to select class B or C
    double (*funcPointer)(std::vector<double>) = firstObj.someFunc; // Error in this line of code

    A finalObj(funcPointer);
}

Так как мне сделать так, чтобы любой класс с функцией-членом данного формата мог использоваться для инициализации класса A?

Ответы [ 4 ]

2 голосов
/ 03 марта 2012

Я не уверен, каковы именно ваши требования, но похоже, что вы хотите интерфейс (или абстрактный базовый класс на C ++).

Если B и C наследуются от общего базового класса, вы можете передать указатель на этот базовый класс и вызвать для него функции:

class I { virtual double func(std::vector<double> a) = 0; }
class B : public I { double func(std::vector<double> a); };
class C : public I { double func(std::vector<double> a); };

Вы можете передать I* указатель на A и просто использовать i->func.

1 голос
/ 03 марта 2012

Вам нужно std::function вместе с std::bind или лямбда-выражениями (или Boost-эквивалентом первых двух), потому что указатели на функции-члены не позволяют вам этого делать.

1 голос
/ 03 марта 2012

Указатель на функцию-член имеет синтаксис, отличный от указателя на обычную функцию, и может указывать только на метод одного данного класса. Чтобы иметь возможность указывать на методы в разных классах, используйте boost :: function или, если доступен C ++ 11, используйте std :: function . Они могут содержать любой метод или функцию с заданной сигнатурой.

0 голосов
/ 03 марта 2012

Вы можете сделать это используя std :: bind + std :: function. Давайте напишем некоторую оболочку класса шаблона, которая принимает любой статический тип в качестве входных данных. Затем используйте эту обертку в бесплатной функции switch_obj. Использование очень просто.

typedef std::function<double(std::vector<double>)> my_foo;

template<class C>
struct switcher
{
    static my_foo convert(C* obj)
    {
        return my_foo( std::bind(&C::someFunc,obj,std::placeholders::_1) );
    }
};

template<class T>
my_foo switch_obj(T* obj)
{
    return switcher<T>::convert(obj);
}

void main()
{
    B firstObj;
    C secondObj;

    auto f =  switch_obj(&firstObj);
    A a(f);
}
...