2017-12-08 16 views
2

Aには多くのBクラスがあり、クラスAには1つのオブジェクトbがあります。このオブジェクトbには、Aのオブジェクトのメソッドへのポインタを必要とする関数(calc)があります。このメソッド(fun)は、クラスのprivate変数にアクセスします(私の例では3を返します)。C++のクラスメソッドへのポインタ

class A; 

class B { 
public: 
    virtual int calc (int (A::*fun)()) { return 2*fun(); }; 
}; 

class A { 
    B* b; 

public: 
    A (B* b_) : b (b_) {}; 
    int fun() { return 3; }; 
    int run(){ return b->calc(&A::fun); }; 
}; 

int main() { 
    B* b = new B(); 
    A a(b); 
    a.run(); 
    return 0; 
} 

どのように私はクラスBでcalcメソッドの定義では正しくメソッドへのポインタを使用することができますか?あなたがC++ 11を使用することができます場合は

teste.cpp:10:58: error: must use ‘.*’ or ‘->*’ to call pointer-to-member  function in ‘fun (...)’, e.g. ‘(... ->* fun) (...)’ 
    virtual int calc (int (A::*fun)()) { return 2*fun(); }; 
                ^
+3

非静的メンバー関数へのポインタは、実際には楽しいですが、そのようなものでは動作しません。私はstd :: functionを調べるだろう – UKMonkey

+3

なぜCの答えはC++の質問の重複としてリンクされていますか?メンバー関数を呼び出すことは、C言語の関数を呼び出すことと同じではありません。 – wally

+0

私はこれがより重複していると信じています。https://stackoverflow.com/questions/12662891/passing-a-member-function-as-an-argument-in- c – UKMonkey

答えて

0

、その後、あなたはstd::functionstd::bindを使用する必要があります:それ以外の場合は、インスタンスにpointer to member function +ポインタを使用する必要が

私は、このエラーメッセージを取得しています。 C++ 11

class B { 
public: 
    virtual int calc (int(A::*fnptr)(), A* a) { return 2 * (a->*fnptr)(); }; 
}; 

class A { 
    B* b; 

public: 
    A (B* b_) : b (b_) {}; 
    int fun() { return 3; }; 
    int run() { return b->calc(&A::fun, this); }; 
}; 

なしC++ 11

#include <functional> 

class B { 
public: 
    virtual int calc (std::function<int()>&& fun) { return 2 * fun(); }; }; 
}; 

class A { 
    B* b; 

public: 
    A (B* b_) : b (b_) {}; 
    int fun() { return 3; }; 
    int run() { return b->calc(std::bind(&A::fun, this)); }; 
}; 

は例hereを参照してください。

0

ポインタ・ツー・クラスメソッドが定義され、初期化として(SomeFnが署名に一致と仮定される):それは場合、私はstd::functionアプローチを勧め

ClassName * ptr = GetClassPtr(); 
(ptr->*pfn)(arg, arg); 
1

RetType (ClassName::*pfn)(Args) = &ClassName::SomeFn; 

として呼ばれていますあなたのために実現可能です。ただし、完全性のために、ここでは、メンバ関数へのポインタを正しく使用する方法を示します。

メンバーへのポインタ自体はAの「現在の」インスタンスを格納しないため、明示的に渡す必要があります。次に、特別な->*(または.*)の構文を使用して呼び出します。

virtual int calc (A* value, int (A::*fun)()) { 
    return 2 * (value->*fun)(); 
}; 

次に、それをb->calc(this, &A::fun);と呼びます。

1

あなたはそれをあなたの方法を行うことができますが、メンバ関数は、特定のインスタンス上calledている必要があります。

class A; 

class B { 
public: 
    virtual int calc(A* a, int (A::*fun)()) { return 2 * (a->*fun)(); }; 
}; 

class A { 
    B* b; 

public: 
    A(B* b_) : b(b_) {}; 
    int fun() { return 3; }; 
    int run() { return b->calc(this, &A::fun); }; // now also passing this pointer 
}; 

int main() { 
    B* b = new B(); 
    A a(b); 
    a.run(); 
    return 0; 
} 

あなたはcalc()が仮想されずに生きることができるならば、ラムダもオプションである:

class A; 

class B { 
public: 
    template<typename T> 
    int calc(T fun) { return 2 * fun(); }; 
}; 

class A { 
    B* b; 

public: 
    A(B* b_) : b(b_) {}; 
    int fun() { return 3; }; 
    int run() { 
     return b->calc([this]() {return fun(); }); 
    }; 
}; 

int main() { 
    B* b = new B(); 
    A a(b); 
    a.run(); 
    return 0; 
} 
関連する問題