C++ 成员函数指针和 STL 算法
Posted
技术标签:
【中文标题】C++ 成员函数指针和 STL 算法【英文标题】:C++ Member Function Pointers and STL Algorithm 【发布时间】:2009-09-20 14:37:32 【问题描述】:我有一个抽象函子类,它重载了 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
我尝试了几种方法,但我不知道如何让它工作,我需要使用抽象类型,因为我可以有不同的派生类型,但它们都必须实现相同的 operator() (参数 x) 函数。
我只需要for_each() 函数就可以调用成员函数operator()(param x)。我有一个不同的函数,它有具体的实现,只需传递一个实例就可以了。我试图在这里达到类似的效果,但不知道我得到了什么具体的课程。
我做错了什么?
【问题讨论】:
为什么不使用vector
而不是指向指针的指针?
@GMan:需要指向指针的指针才能使数组中的每个项目都属于从 A 派生的任何类型(否则你会得到切片)。向量在这里实际上并没有多大帮助,因为它不会自动 delete
它的指针成员——您需要为此使用智能指针向量。
好的,但是请修复function()
的主体——目前for 循环大括号没有关闭! it
是什么? X
是什么? (你的意思是x
而不是X
?)等等。
等一下——operator()()
s 是否都采用相同类型的单个参数?如果是这样,那么我很惊讶函数定义甚至可以编译......当然编译器无法区分函数类型,因为它们是相同的类型!
你把我的static_cast<>
建议弄错了(pFunc
不是一个类型),bind1st()
想要一个指向对象的指针,而不是一个对象。试试for_each(it->second.begin(), it->second.end(), std::bind1st(std::mem_fun(pFunc), pf));
【参考方案1】:
你想要这样的东西......
std::for_each(
it->second.begin(),
it->second.end(),
std::bind1st(std::mem_fun(&A::operator()),x)
);
【讨论】:
不错。此外,来自常规 C++03 标准的bind1st()
将代替您在此处使用的更通用的 std::tr1::bind()
(可能尚未得到所有编译器的支持)。
一个很好的例子,说明你可以使用 C++ 实现多么通用,但它对眼睛来说太痛苦了。 :-/
mem_fun() 将一元成员函数 - 称为 obj->fun(arg) - 转换为二元普通函数 - 称为 fun(obj,arg)。
这对我来说无法编译 :( 我得到:错误:没有匹配的函数用于调用“mem_fun(mem_fun(static_cast<void (A::*)(param)>(&A::operator())
【参考方案2】:
如果我理解你想要做什么,你的代码 sn-p 中有很多错误:
sizeof aArr
错误,您需要明确传递大小(ChrisW 注意到)
operator()()
的原始声明中缺少 virtual
说明符
不确定您的 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()
生成一个单参数函数对象,该对象将提供给function()
的参数固定为第二个参数。 (for_each()
需要一个 1 参数的函数指针或函数对象。)
编辑:基于Alex Tingle's answer,我推断您可能希望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]));
【讨论】:
是的,我会尝试,因为这是完整的标准 c++。我确实有虚拟我只是忘了把它从示例中删除,我也会修复 arr 的大小。如果可行,我会回帖,应该可以。 使用 for_each 循环,它实际上是在处理一些值的向量。所以我需要仿函数来处理这些数据。所以 for_each(v.begin(), v.end(), func) 其中 v 是向量, func 是我试图从 aArr 中取出的指针 如果您重读,您可能会发现我预料到了... :) 如果没有,请告诉我需要更改的内容。 是的,我无法使用任何解决方案,我想我可能做错了什么。作为一个普遍的问题,如果你给定的只是一个指向实例的指针,你将如何获得一个指向成员函数的指针? 您是否意识到“pointer-to-member-function”与“pointer-to-function”的类型不同? 不可能从一种转换为另一种。但是,您可以使用bind1st(mem_fun(pMemFunc), pObj)
从指针到对象和指针到成员函数的组合中获取可以像函数一样调用的对象。【参考方案3】:
表达式“bar.*fn”不会计算为常规或非成员函数指针。 因此,您需要调用绑定函数( std::tr1::bind 或 boost::bind )来获得这样的函数。
【讨论】:
【参考方案4】:我无法使用当前格式使其工作,我认为它不喜欢我使用指向基成员函数的指针并试图调用这样的派生类实现这一事实。
相反,我修改了代码以在基类中包含纯虚函数,这些函数在实现时将为每个派生类返回函子。我想不出还有什么可以用的。但它是这样编译的。
但我很好奇是否有人可以解决原始问题而不必在基类中使用纯虚拟“创建函子”方法。
【讨论】:
以上是关于C++ 成员函数指针和 STL 算法的主要内容,如果未能解决你的问题,请参考以下文章
C++|详解类成员指针:数据成员指针和成员函数指针及应用场合