Указатели на функции-члены C++ и алгоритм STL
У меня есть абстрактный класс функторов, который перегружает operator() и производные объекты, которые его реализуют.
У меня есть функция (часть другого класса), которая пытается взять массив этих классов функторов и пытается передать указатель на функцию-член алгоритму std for_each(), вот обзор того, что я делаю:
РЕДАКТИРОВАТЬ: я повторно очистил его и поместил старый маленький пример для ясности.
class A{
operator()(x param)=0;
operator()(y param)=0;
}
class B: public A{
operator()(x param); //implemented
operator()(y param);
}
...// and other derived classes from A
void ClassXYZ::function(A** aArr, size_t aSize)
{
...//some code here
for(size_t i = 0; i< aSize; i++){
A* x = aArr[i];
for(v.begin(), v.end(), ...//need to pass pointer/functor to right operator() of x here
..//other code
}
Я пробовал несколько способов, и я не могу понять, как заставить его работать, мне нужно использовать абстрактный тип, так как у меня могут быть разные производные типы, но все они должны будут реализовывать один и тот же оператор ()(параметр х) функция.
Мне просто нужно, чтобы функция for_each () могла вызывать функцию-член operator()(param x). У меня есть другая функция, где она имеет конкретные реализации и просто передает их, и это работает. Я пытаюсь добиться подобного эффекта здесь, но без знания того, какие конкретные занятия мне дают.
Что я делаю неправильно?
4 ответа
Если я понимаю, что вы хотите сделать, в вашем фрагменте кода довольно много ошибок:
sizeof aArr
неверно, вам нужно явно указать размер (замечено ChrisW)- Отсутствует
virtual
спецификатор в оригинальной декларацииoperator()()
- Не уверен, где ваш
for
цикл заканчивается, так как нет соответствия}
(Я подозреваю, что это не должно быть там вообще)
Вот код, который будет проходить через массив A
(или же A
предметы и вызов operator()
на каждом, передавая переданный аргумент как param
параметр:
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef double param; // Just for concreteness
class A {
public:
virtual void operator()(param x) = 0;
};
class B : public A {
public:
void operator()(param x) { cerr << "This is a B! x==" << x << ".\n"; }
};
void function(A** aArr, size_t n, param theParam) {
void (A::*sFunc)(param x) = &A::operator();
for_each(aArr, aArr + n, bind2nd(mem_fun(sFunc), theParam));
}
int main(int argc, char** argv) {
A* arr[] = { new B(), new B(), new B() };
function(arr, 3, 42.69);
delete arr[0];
delete arr[1];
delete arr[2];
return 0;
}
mem_fun()
необходимо преобразовать указатель функции-члена с 1 параметром в объект функции с 2 параметрами; bind2nd()
затем производит из этого объекта функции с 1 параметром, который фиксирует аргумент, предоставленный function()
как второй аргумент. (for_each()
требуется указатель на функцию с 1 параметром или функциональный объект.)
РЕДАКТИРОВАТЬ: Исходя из ответа Алекса Тингла, я делаю вывод, что вы, возможно, хотели function()
делать много вещей на одном A
объект В этом случае вам нужно что-то вроде:
void function(A** aArr, size_t n, vector<param> const& params) {
for (size_t i = 0; i < n; ++i) {
void (A::*sFunc)(param x) = &A::operator();
for_each(params.begin(), params.end(), bind1st(mem_fun(sFunc), aArr[i]));
}
}
Вы хотите что-то вроде этого...
std::for_each(
it->second.begin(),
it->second.end(),
std::bind1st(std::mem_fun(&A::operator()),x)
);
Выражение "bar.* Fn " не соответствует обычному или не являющемуся членом функции указателю. Поэтому вам нужно вызвать функцию привязки (либо std::tr1::bind, либо boost::bind), чтобы получить такую функцию.
Я не мог заставить его работать, используя текущий формат, я думаю, что ему не нравится тот факт, что я использую Pointer для базовой функции-члена и пытаюсь вызвать реализацию производных классов таким образом.
Вместо этого я изменил код, включив в базовый класс чисто виртуальные функции, которые будут возвращать функторы для каждого производного класса при реализации. Я не могу думать ни о чем другом, что сработало бы. Но это компилируется следующим образом.
Но мне любопытно, есть ли у кого-нибудь решение исходной проблемы без необходимости использования чисто виртуальных методов "создания функтора" в базовом классе.