2012-03-03 4 views
3

Вот требования, предъявляемые моим приложением. У меня есть класс 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?

+0

Вам действительно нужны функции, которые должны быть функциями-членами? – Mat

+0

Не очень, но функции будут очень тесно интегрированы с переменной класса, так что, кажется, лучший способ пойти. – Nicomoto

ответ

2

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

Если оба 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 ,

+0

Я должен не согласиться с вами. Иногда вам нужен только статический полиморфизм. – innochenti

+0

@innochenti: Это так же хорошо, как использование глобальных функций. Я предложил только интерфейсы, потому что OP шел объектно-ориентированным способом. – casablanca

1

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

1

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

0

Вы можете сделать это, используя 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); 
}