2

我试图通过传递一个函数指针来让这样的东西工作。我知道您可以将第一个类的指针传递给第二个类,然后让第二个类通过指针触发第一个类的成员函数。但我不希望二等舱依靠知道谁是一等舱。这更像是我正在寻找实现这一目标的编码风格。谢谢

//////////////////////////////////////////////////
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

4 回答 4

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();
 } 
于 2012-04-24T04:01:32.130 回答
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
} 

请阅读此常见问题解答以获取更多信息。

于 2012-04-24T04:21:06.047 回答
2

您应该阅读如何在 C++ 中实现回调?并特别注意对观察者模式的引用。如果您有两个这样紧密耦合的类,那么您可能需要重新考虑您的设计,因为测试它们很快就会变成一场噩梦。

也就是说,这里是如何完成你开始的实施......

#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;
}

看它跑


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

#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;
}
于 2012-04-24T04:26:27.713 回答
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;
}
于 2012-04-24T04:28:17.177 回答