2

関数ポインタを渡すことで、このようなものを機能させようとしています。最初のクラスのポインターを2番目のクラスに渡して、2番目のクラスにポインターを介して最初のクラスのメンバー関数を起動させることができることを私は知っています。しかし、私は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 ++でコールバックを実装するにはどうすればよいですか?を読む必要があります。オブザーバーパターンへの参照に特に注意してください。このように緊密に結合されたクラスが2つある場合は、それらのテストがすぐに悪夢になるため、設計を再考する必要があります。

そうは言っても、これがあなたが始めた実装を終了する方法です...

#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 に答える