转换方法签名

时间:2010-02-18 11:35:35

标签: c++ visual-studio-2008 casting type-conversion

typedef void(__ thishisall * LPVOIDPROC)(void);

class ClassA
{
  LPVOIDPROC m_pProc;

  void SetProc(LPVOIDPROC pProc)  { m_pProc = pProc; }

  void OnSomeEvent() { m_pProc(); }
}

class ClassB
{
  ClassA* pCA;

  void Proc() { /* ... */ }

  void Init()
  {
    // Assume pCA != NULL
    pCA->Set((LPVOIDPROC)&ClassB::Proc); // error C2440
  }
}

如何摆脱这个错误C2440:'type cast':无法从'void(__ thiscall ClassB :: *)(void)'转换为'LPVOIDPROC'?我不想将LPVOIDPROC签名仅限制为ClassB。这应该是任何类,引用的proc不应该是静态的。

5 个答案:

答案 0 :(得分:3)

解决方法:

typedef void (* CLASSPROC) (void *); 

template<class T, void (T::*proc)()>
void class_proc(void * ptr) 
{
 (static_cast<T*>(ptr)->*proc)();
}

class ClassA 
{ 
 CLASSPROC m_pProc;
 void    * m_pInstance;

public:
 void SetProc(void *pInstance, CLASSPROC pProc)  { 
          m_pInstance = pInstance; 
          m_pProc = pProc; 
     } 

 void OnSomeEvent() { m_pProc(m_pInstance); } 
};

class ClassB 
{ 
 ClassA* pCA; 

 void Proc() { /* ... */ } 

 void Init() 
 { 
  // Assume pCA != NULL 
  pCA->SetProc(this, class_proc<ClassB, &ClassB::Proc>);      
 } 
};

答案 1 :(得分:2)

我推荐你link。您的类型LPVOIDPROC指向函数的指针,它与指向成员函数的指针不同。当您尝试转换ClassB::Proc时,您正在尝试将指针转换为成员函数,这是一种无效的操作。

你应该看看boost::function,它提供你正在寻找的东西。或者,如果您不想求助,可以使用仿函数来封装函数。例如:

struct VoidProcFunctor {
    virtual void call() = 0;
};

class ClassB;
struct BProcFunctor : VoidProcFunctor {
    BProcFunctor(ClassB* b) : b_(b) {}
    void call();
private:
    ClassB* b_;        
}

class ClassA
{
public:
    VoidProcFunctor* m_pProc;

    void SetProc(VoidProcFunctor* pProc)  { m_pProc = pProc; }

    void OnSomeEvent() { m_pProc->call(); }
};

class ClassB
{
    ClassA* pCA;

    void Proc() { /* ... */ }

    void Init()
    {
        // Assume pCA != NULL
        // warning! this is not the best design possible
        BProcFunctor* bproc = new BProcFunctor(this);
        pCA->SetProc(bproc);
    }
};

void BProcFunctor::call() { b_->proc() }

答案 2 :(得分:0)

非静态方法需要一个'this'指针,没有'this'指针你无法调用它,因此将它转换为C函数指针是没有意义的。

考虑制作一个具有

的简单类(让我们称之为X)
  • 引用ClassB实例的数据成员
  • a()运算符(虽然我更喜欢具有明确名称的方法)使用ClassB实例作为this-pointer调用ClassB :: Proc。

不是将函数指针传递给类A,而是创建一个X实例(其数据库为ClassB填充)并将其传递给类A. 而不是调用函数指针类A应该调用x()。

甚至可以使用模板编写X类,因此如果您有多个类的情况,则必须只编写一次。

我认为在C#中,使用代理可以更清晰,但我将其留给C#和.Net专家。

答案 3 :(得分:0)

  1. 永远不会转换函数指针。最终可能会出现堆栈损坏。不要这样做。

  2. 不要将指针传递给非静态成员函数。它们使用不同的调用约定并且不兼容。

  3. 在您的情况下,将“Proc()”设为静态可能会解决问题。

答案 4 :(得分:-1)

您需要将Proc方法作为静态方法。