2012-01-24 9 views
1

私はC++を学んでいるだけで、メソッドへのポインタに関しては問題があります。教えてください:メソッドへのポインタのトラブル

class One { 
public: 
int Add (int a, int b) {return a+b;} 
}; 

typedef int (One::*pAdd) (int, int); 

class Other { 
public: 
int Next (pAdd funct, int c){ return funct (c, 1);} 

}; 

int main(){ 

One one; 
Other other; 

other.Next(one.Add, 2); 

return 0; 
} 

私はMinGWによって報告されたように私はいくつかの問題があります。まず、コンパイラが。*または - > *の使用を主張しているので、私はfunctを正しく起動していません。この要請をどのように組み込むべきかわからず、どんな援助も歓迎されます。今、メソッドを静的にしてCスタイルのポインタやオブジェクトを渡し、Nextからメソッドを呼び出すことで問題を解決できましたが、メソッドへのポインタを理解したいと思います。基本的に、私はなぜone.Addが受け入れられる入力ではないのか困惑しています。呼び出すメソッドは明白に定義され(.Add)、私のtypedefに準拠しています。また、私はtypedefからクラス(1)のインスタンスを提供しているので、メソッドが実行されるコンテキストを提供しています。しかし、コンパイラの出力は、私が構文を逃しただけでなく、コンセプトを逃したように見えます。オブジェクトへのポインタをコンテキストとして単一の引数として渡す方法は?

+0

:ここ

は、コードを働いて、変更されました。私はコミュニティに謝罪しますが、どのように質問を削除しますか? –

+2

@gxsだけ移行されます。 –

+0

こんにちはgxs、あなたの質問が自動的にStackOverflowに移動できるようにモデレータが通知されます。これはプログラマーであり、ソフトウェア開発に関する概念的な質問のサイトです。詳細については、std :: bind/boost :: bindとlambdaの提案について[FAQ](http://programmers.stackexchange.com/faq) –

答えて

6

ここでの主な問題は、メンバ関数がオブジェクトインスタンスに関連付けられていないことです。これらは、わずかに異なるシグネチャを持つ関数ポインタです。メンバ関数へポインタと、それを呼び出すことでオブジェクトインスタンス:あなたはメンバ関数を呼び出したいとき

だから、あなたは二つのことを必要とします。今

#include <iostream> 

class One { 
public: 
    int Add (int a, int b) {return a+b;} 
}; 

typedef int (One::*pAdd) (int, int); 

class Other { 
public: 
    int Next (One one, pAdd funct, int c){ 
     return (one.*funct)(c, 1); 
    } 
}; 

int main(){ 
    One one; 
    Other other; 

    std::cout << other.Next(one, &One::Add, 2) << std::endl; 

    return 0; 
} 

そしてit works

は、私はあなたのコードサンプルビットを変更しました。それはおそらく少し改善することができますが、私はあなたがここからそれを取ることができると思います。

c++ faq litePointers to member functionsセクションを読むことをお勧めします。これはこれを非常にうまく説明しています。

0

メンバへのポインタは、操作するインスタンスを必要とします。基本的には、暗黙のthisポインタになる加算パラメータをとる関数です。

(this->*funct)(c, 1); 

(あなたが同様にメンバ変数にアクセスするが、関数呼び出しのないと思います):現在のオブジェクトのメンバにポインタを使用して関数を呼び出すするには、このようなコードを使用することができます。

メンバーを呼び出したオブジェクトは、メンバーへのポインタの一部ではありません。その結果、あなたはそれをこのような何かを取得する必要があります。この場合、あなたはアドレスを取ったときに過負荷を決定することができ、そこからコンテキストを提供する必要があります。これは、メンバ関数がオーバーロードされている場合より面白いとなり

&One::Add 

。私はtupicallyこのためstatic_cast<>()を使用します。

static_cast<int (One::*)(int,int)>(&One::Add) 
1

だから、どのように1つの引数としてコンテキストとオブジェクトとメソッドへのポインタを渡しますか?

メンバー関数ポインタだけを使用することはできません。あなたの構文はそれを行うべきもののように見えますが、それは許されません。「あなたは、特定のオブジェクトの特定のメンバ関数を呼び出す関数オブジェクトを作成したい場合は、一つの可能​​性はあなたができればstd::bind(またはboost::bindを使用することです

class Other { 
public: 
    int Next (pAdd funct, One & o, int c){ return (o.*funct) (c, 1);} 
} 

int main(){ 
    One one; 
    Other other; 
    other.Next(&One::Add, one, 2); 
} 

:あなたはに関数を適用するオブジェクトが必要ですトンまだC++ 11)を使用します。

#include <functional> 

class Other { 
public: 
    int Next (std::function<int(int,int)> funct, int c){ return funct (c, 1);} 
}; 

int main(){ 
    One one; 
    Other other; 

    using namespace std::placeholders; 
    other.Next(std::bind(&One::Add, &one, _1, _2), 2); 
} 

またはラムダ:

other.Next([&](int a, int b){return one.Add(a,b);}, 2); 
+0

+1を参照してください。 –

0

あなたがここでの問題の束を持っている:one.Addは、メンバーのfuであります を呼び出すことはできません。 にも同様に呼び出すクラスへのポインタが必要です。また、operator.* またはoperator->*の特殊文字を使用する必要があります。また、束縛されたメンバーのアドレスを受け取ることはできません 機能。

テンプレートとboost/std::bindを使用すると、 はすべてこのように耐えられるか、離れないようにしてください。私はちょうど実現...それらの両方が開かれ、間違ったタブに掲載されていた

class One { 
public: 
    int Add (int a, int b) {return a+b;} 
}; 

typedef int (One::*pAdd) (int, int); 

class Other { 
public: 
    int Next (One* one, pAdd funct, int c){ return (one->*funct)(c, 1);} 
}; 

int main(){ 

    One one; 
    Other other; 

    other.Next(&one, &One::Add, 2); 

    return 0; 
} 
関連する問題