使用函数指针在类之间传递数据

时间:2012-04-24 03:44:39

标签: c++ class function pointers member

我试图通过传递函数指针来实现这样的工作。我知道你可以将第一个类的指针传递给第二个类,然后通过指针获取第二个类的成员函数。但我不希望第二堂课依赖于知道第一堂课是谁。这更像是我想要实现这一目标的编码风格。感谢

//////////////////////////////////////////////////
class Second
{
public:
    Second::Second(void (*SecondTriggered)(void));
};

Second::Second(void (*SecondTriggered)(void))
{
    SecondTriggered();
}


//////////////////////////////////////////////////
class First
{
public: 
    First::First();
    void SecondTriggered();
    Second *second;
};

First::First(){
        printf("first class was created"); 
    second = new Second(SecondTriggered);
}

void First::SecondTriggered(){
    printf("second class was created and responded"); 
}

/////////////////
int main()
{
    First *first = new First();
 } 

我收到此错误:

error C3867: 'First::SecondTriggered': function call missing argument list; 
use '&First::SecondTriggered' to create a pointer to member

任何想法。

4 个答案:

答案 0 :(得分:3)

您正在尝试传递一个非静态类成员,其中需要一个独立的函数。要做你正在尝试的事情,你将不得不做以下的事情:

class Second
{
public:
    Second::Second(void (*SecondTriggered)(void*), void *arg);
};

Second::Second(void (*SecondTriggered)(void*), void *arg)
{
    SecondTriggered(arg);
}


//////////////////////////////////////////////////
class First
{
public: 
    First::First();
    static void SecondTriggered(void *arg);
    Second *second;
    void DoSomething();
};

First::First(){
    printf("first class was created"); 
    second = new Second(&SecondTriggered, this);
}

void First::SecondTriggered(void *arg){
    printf("second class was created and responded"); 
    static_cast<First*>(arg)->DoSomething();
}

void First::DoSomething(){
    printf("first class did something");
}

/////////////////
int main()
{
    First *first = new First();
 } 

答案 1 :(得分:2)

请记住,指向成员函数和函数指针的指针是非常不同的。您必须有一个对象来调用指向成员函数的指针。如果你想使用指向成员函数的指针,下面的代码可以工作(我只显示了使代码工作的语法。我建议在使用指向成员函数的指针之前理解C ++概念):

#include <stdio.h>
//////////////////////////////////////////////////
class First; // Forward declaration needed

class Second
{
public:
    Second(void (First::*SecondTriggered)(void), First& f);
};

Second::Second(void (First::*SecondTriggered)(void), First& f)
{
    (f.*SecondTriggered)();
}


//////////////////////////////////////////////////
class First
{
public: 
    First();
    ~First() { delete second;} // Fix memory leak
    void SecondTriggered();
    Second *second;
};

First::First(){
    printf("first class was created\n"); // What are you using printf in C++? 
    second = new Second(&First::SecondTriggered, *this);
}

void First::SecondTriggered(){
    printf("second class was created and responded\n"); 
}

/////////////////
int main()
{
    First first; // No reason to use new here
} 

请阅读this faq了解详情。

答案 2 :(得分:2)

您应该阅读How do I implement a callback in C++?并特别注意对Observer Pattern的引用。如果你有两个这样紧密耦合的类,那么你可能想重新考虑你的设计,因为测试它们很快就会成为一场噩梦。

那就是说,这是如何完成你开始的实现......

#include <iostream>

class First;

// Typedefs make this much more readable: http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.5
typedef void (First::*SecondTriggeredCallback)(void);

// And macros make the call much more readable:  http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.6
#define CALL_MEMBER_FN(object, ptrToMember) ((object).*(ptrToMember))

class Second
{
public:
    // You'll also need an *instance* of the First class
    Second(SecondTriggeredCallback SecondTriggered, First& first)
    {
        CALL_MEMBER_FN(first, SecondTriggered)();
    }
};

class First
{
private:
    Second *second;

public:
    First()
    {
        std::cout << "first class was created" << std::endl;
        second = new Second(&First::SecondTriggered, *this);
    }

    ~First()
    {
        delete second;
    }

    void SecondTriggered()
    {
        std::cout << "second class was created and responded" << std::endl;
    }
};

int main()
{
    First first;
}

See it run


这是一个使用模板删除耦合的版本:

#include <iostream>

// Macros make the call much more readable: http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.6
#define CALL_MEMBER_FN(object, ptrToMember) ((object).*(ptrToMember))
template <class T>
struct Second
{
    // Typedefs make this much more readable: http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.5
    typedef void (T::*SecondTriggeredCallback)(void);

    // You'll also need an *instance* of the "T" class
    Second(SecondTriggeredCallback SecondTriggered, T& t)
    {
        CALL_MEMBER_FN(t, SecondTriggered)();
    }
};

class First
{
public:
    First()
        :second(NULL)
    {
        std::cout << "first class was created" << std::endl;
        second = new Second<First>(&First::SecondTriggered, *this);
    }

    ~First()
    {
        delete second;
    }

    void SecondTriggered()
    {
        std::cout << "second class was created and responded" << std::endl;
    }

private:
    First(const First&);
    First& operator =(const First&);
    Second<First>* second;
};

int main()
{
    First first;
}

答案 3 :(得分:1)

您也可以考虑传递一个函数对象:

class t_func {
protected:
    t_func() {
    }

    virtual ~t_func() {
    }

public:
    virtual void operator()() = 0;
private:
    t_func(const t_func&) = delete;
    t_func& operator=(const t_func&) = delete;
};

class Second {
public:
    Second(t_func& func);
};

Second::Second(t_func& func) {
    func();
}

class First {
public:
    First();
private:
    void SecondTriggered();
    Second* second;
};

First::First() {
    printf("first class was created\n");

    class t_trigger : public t_func {
    public:
        t_trigger(First& pFirst) : t_func(), first(pFirst) {
        }

        virtual void operator()() {
            return first.SecondTriggered();
        }

    private:
        First& first;
    };

    t_trigger trig(*this);
    second = new Second(trig);
}

void First::SecondTriggered() {
    printf("second class was created and responded\n");
}

int main() {
    First* first = new First();

    delete first;
    return 0;
}