如何将指针作为参数传递给方法?

时间:2016-04-19 12:18:55

标签: c++

我想将一个方法作为参数传递给一个接受int并返回void的方法:

test()

Error 1 error C2664: cannot convert parameter 1 from 'void (__thiscall B::* )(int)' to 'void (__cdecl *)(int)' 内我收到此错误:

Document
+----+---------------+-----------------+
| id | name          | description     | 
+----+---------------+-----------------+
| 1  | BriefDocument | Something       |    
+----+---------------+-----------------+

DocumentData
+----+--------------+-----------------+--------------+
| id | key          | value           | documentId   |
+----+--------------+-----------------+--------------+
| 1  | whatData     | inputted data   | 1            |  
+----+--------------+-----------------+--------------+
| 2  | whoData      | inputted data   | 1            |  
+----+--------------+-----------------+--------------+
| 3  | whyData      | inputted data   | 1            |  
+----+--------------+-----------------+--------------+
| 4  | howData      | inputted data   | 1            |  
+----+--------------+-----------------+--------------+

我在StackOverflow上看到了一些如何解决这个问题的例子,但它使用了C ++ 11中我无法访问的元素。
如何使用C ++ 03解决这个问题?

4 个答案:

答案 0 :(得分:4)

您不能将非静态方法传递给带有指向函数的指针的函数。功能和方法是两个完全不同的东西。为了调用非静态方法,显然你必须拥有一个你正在调用它的方法的对象。

如果在您的示例中Done()是静态类方法,那么,是的,您可以通过这种方式传递它,因为静态类方法只是函数的另一个名称。

可以有一个指向类方法的指针:

void A::SetCallback(void (B::*callback)(int))
{

}

void B::test()
{
   a->SetCallback(&B::Done); //
}

void B::Done(int i)
{
   ..........................
}

但是为了调用类方法,你需要一个调用方法的对象:

B *object=give_me_a_pointer_to_b_from_somewhere();

(object->*callback)(0);

答案 1 :(得分:2)

&ClassName::method_name创建指针,void(ClassName::*)(int, char*)是类型。

void go(void(ClassName::*parameter_name)(int, char*));

go(&ClassName::method_name);

答案 2 :(得分:1)

您不能将指向类方法(在您的情况下为void (B::*) (int)类型)的指针传递给指向自由函数的指针。

如果可以,会发生什么?

void f (void (*g) (int)) {
    g(2);
}

struct A {
    int x;
    void foo (int c) { x += c; }
};

f(&A::foo); // Oh oh! Where will I find `x` in the call `g(2)`?

如果您只想指向B的方法,则需要更改回调类型:

void A::SetCallback(void (B::*callback)(int)) { }

但是你需要一个B的实例来调用你的回调,例如:

B b;
(b.*callback)(2);

答案 3 :(得分:1)

我使用以下代码。它不漂亮,但你要求C ++ 03:

#include <iostream>
#include <vector>
#include <functional>

class AbstractCallback {
public:
    virtual void call(int arg) = 0;
};

template <class T>
class Callback : public AbstractCallback {
public:
    typedef std::mem_fun1_t<void, T, int> CallbackFunc;
private:
    CallbackFunc func;
    T* object;
public:
    Callback(T* _object, const CallbackFunc& _func)
        : object(_object), func(_func) {
    }

    void call(int arg) {
        func(object, arg);
    }
};

struct A {
    void foo(int a) {
        std::cout << "foo " << a << std::endl;
    }
};
struct B {
    void bar(int a) {
        std::cout << "bar " << a << std::endl;
    }
};

int main() {
    A a;
    B b;

    AbstractCallback* cbs[2] = {
        new Callback<A>(&a, std::mem_fun(&A::foo)),
        new Callback<B>(&b, std::mem_fun(&B::bar)),
    };

    cbs[0]->call(10);
    cbs[1]->call(22);

    delete cbs[0];
    delete cbs[1];

    return 0;
}

正如您所见,指针成员函数(类型A::*B::*)被包装到std::mem_fun和一个为每种类型生成的Callback类中(在这种情况下为AB)。

这允许在矢量,数组或抽象回调列表中保留任何类型的方法。