[英]Pointer to function from a member's function
我的情况有点复杂。 它可以很容易地通过继承来解决,但是我现在很好奇,由于其他一些原因,我会用这种方式解决它。
我有代表算法的课程,随着时间的推移,已经实现了不同的解决方案。 目前,我拥有原始班级,并且它的成员是新班级。 我将同时拥有算法和开关,以便能够根据情况使用它们。
#include "B.h"
class A {
public:
typedef void ( A::*FooFunction )( float, float );
A::FooFunction m_fooFunction;
B m_b;
A( WhichUseEnum algorithm ) : m_b( B() )
{
switch( algorithm ) {
case ALG_A:
m_fooFunction = &A::FooFunctionOfA;
break;
case ALG_B:
m_fooFunction = ??? // something like: m_b.FooFunctionOfA
break;
}
}
void FooFunction( float a , float b)
{
( this->*m_fooFunction )( a, b );
}
void FooFunctionOfA( float, float ); // implementation at the .cpp
};
class B {
public:
void FooFunctionOfB( float, float );
}
如您所见,我想保存指向成员m_b的函数的指针,并像FooFunction那样调用它。 使用自己的函数(FooFunctionOfA()),我已经成功了,但是另一个要困难得多。 我尝试了几种方法,但是找不到编译器接受的版本。 :)
我发现了一个类似的问题,解决方案如下所示: &m_b.*m_b.FooFunctionOfB
,此时我放弃了。
如果有人有想法,请不要犹豫与我分享。
我正在使用C ++,但未使用C ++ 0x,因此不得不避免使用stl和boost。
您需要使用std::tr1::function
。 此类是为您需要的目的而构建的。 它可以接受任何函数,成员函数等。
class A {
public:
std::tr1::function<void(float, float)> m_fooFunction;
B m_b;
A( WhichUseEnum algorithm ) : m_b( B() )
{
switch( algorithm ) {
case ALG_A:
m_fooFunction = std::tr1::bind(&A::FooFunctionOfA, this);
break;
case ALG_B:
m_fooFunction = std::tr1::bind(&A::FooFunctionOfA, &m_b);
break;
}
}
void FooFunction( float a , float b)
{
m_fooFunction( a, b );
}
void FooFunctionOfA( float, float ); // implementation at the .cpp
};
class B {
public:
void FooFunctionOfB( float, float );
}
在这里,我使用了std::tr1::bind
来定义两个函数。 如您所见,调用语法也很容易-就像常规函数调用一样。 std::tr1::bind
可以绑定成员函数和成员函数指针,还可以绑定很多东西。 Gah,已经有一段时间了,因为我不得不使用bind
而不是lambda。
C ++的一般规则是,如果您使用函数指针或成员函数指针,并且没有与某些旧代码交互,则几乎可以肯定它做错了。 也不例外。 如果您使用的是C ++ 0x之前的版本,则可能也需要bind
它们,仅此而已。
如果您使用的编译器太旧了, 甚至没有TR1 ,则可以使用Boost来替代这些功能-它们是Boost的Standardized,因此Boost的等效功能和接口都非常接近。
您可以提供一个完成该任务的包装函数。
#include "B.h"
class A {
public:
typedef void ( A::*FooFunction )( float, float );
A::FooFunction m_fooFunction;
B m_b;
A( WhichUseEnum algorithm ) : m_b( B() )
{
switch( algorithm ) {
case ALG_A:
m_fooFunction = &A::FooFunctionOfA;
break;
case ALG_B:
m_fooFunction = &A::FooFunctionOfB;
break;
}
}
void FooFunction( float a , float b)
{
( this->*m_fooFunction )( a, b );
}
void FooFunctionOfA( float, float ); // implementation at the .cpp
// A wrapper function that redirects the call to B::fooFunctionOfB().
void FooFunctionOfB( float a, float b)
{
this->m_b.FooFunctionOfB(a, b);
}
};
class B {
public:
void FooFunctionOfB( float, float );
}
您应该做什么:
(1)在原始算法上提取接口。 现在,原始算法是此虚拟接口的实现。
class FooFunctionInterface
{
public:
virtual void Foo(float a, float b) = 0;
};
class OriginalFoo : public FooFunctionInterface
{
public:
void Foo(float a, float b) override
{
/* ... original implementation ... */
}
};
(2)介绍新算法作为接口的替代实现。
class NewFoo : public FooFunctionInterface
{
public:
void Foo(float a, float b) override
{
/* ... new implementation ... */
}
};
(3)引入工厂功能以选择要使用的实现。
class NullFoo : FooFunctionInterface
{
public:
void Foo(float a, float b) override {}
};
std::unique_ptr<FooFunctionInterface> FooFactory(WhichUseEnum which)
{
std::unique_ptr<FooFunctionInterface> algorithm(new NullFoo());
switch(which)
{
case ALG_A: algorithm.reset(new OriginalFoo()); break;
case ALG_B: algorithm.reset(new NewFoo()); break;
};
return algorithm;
}
然后,您的A类成为pimpl惯用语,将调用转发到适当的实现。
class A
{
public:
A(WhichUseEnum which)
: pimpl_(FooFactory(which))
{
}
void Foo(float a, float b)
{
pimpl_->Foo(a, b);
}
private:
std::unique_ptr<FooFunctionInterface> pimpl_;
};
大大简化了您造成的混乱。 当您考虑需要添加第三个实现,然后添加第四个实现时,会发生什么,就知道它的清除器。
在我的示例中,您扩展了工厂功能并继续前进。 没有其他代码更改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.