将指针指向基类的受保护方法并将其传递给其他类

时间:2015-01-06 13:18:34

标签: c++ inheritance member-function-pointers

template <typename... Arguments>
class CCallback
{
public:
    template <class TargetClass>
    CCallback(TargetClass * target, void (TargetClass::*targetMethod)(Arguments...))
    {
    }
};

struct TargetClassBase
{
protected:
    void f() {}
};

struct TargetClassChild : TargetClassBase
{
    void g() {}

    void test()
    {
        CCallback<> callback(this, &TargetClassChild::f);
    }
} child;


void main()
{
}

该代码无法在MSVC 2013中编译:

  

错误C2660:'CCallback&lt;&gt; :: CCallback':函数不带2   参数

我不明白为什么我会遇到这个特定的错误,以及如何让它工作。没有关于编译器记录的错误的更多细节。

当然,我无法正确指定该方法属于基类(&TargetClassBase::f) - 禁止指向非公共基本方法。

2 个答案:

答案 0 :(得分:1)

代码问题在于编译器无法在TargetClass的构造函数中推导出模板类型CCallback。这是因为您将类型的参数:TargetClassChild*void (TargetClassBase::*)()传递给构造函数。这不是一个错字。即使你写&TargetClassChild::f,这个表达式仍然有类型:指向函数的指针,返回类 TargetClassBase 中的void而不是 TargetClassChild ,就像人们所期望的那样。

这种问题可以通过两种方式解决:

  1. 您可以明确指定模板类型,但在这种特殊情况下无法完成,因为在C ++中无法将模板参数显式传递给构造函数,因为构造函数没有名称(根据§14.5.2.5中的注释) c ++标准)。
  2. 将适当类型的参数传递给函数。在这种情况下,只需将您的函数转换为适当的类型,如static_cast<void (TargetClassChild::*)()>(&TargetClassChild::f)

答案 1 :(得分:0)

扩展了robal的完美正确答案,我重写了我班级的构造函数,这样我就不需要手动类型转换了:

template <class TargetInstanceClass, class TargetMethodClass>
CCallback(TargetInstanceClass * target, void (TargetMethodClass::*targetMethod)(Arguments...))
{
   void (TargetInstanceClass::*targetInstanceMethod)(Arguments...) = static_cast<void (TargetInstanceClass::*targetInstanceMethod)(Arguments...)>(targetMethod);
}