関数ポインタの使い方で悩んでいます。
下記の
(1)のようにグローバルメソッドとして定義したメソッドを関数ポインタに代入することは出来るのですが、
(2)のようにクラスのメンバメソッドとして定義したメソッドは関数ポインタに代入することは出来ませんでした。
Error:バインドされた関数へのポインターは関数の呼び出しにのみ使用できます。
というエラーが発生します。
関数ポインタに外部参照でメソッドを代入することは出来ないのでしょうか?
-----(1)------------------------------------------------------------------
#include "stdafx.h"
#include <iostream>
using namespace std;
int f(int a, int b){
return a * b;
}
int _tmain(int argc, _TCHAR* argv[])
{
typedef int (* FUNC_POINTER)(int, int);
FUNC_POINTER fp;
fp = f;
cout << fp(1,2) <<endl;
getchar();
return 0;
}
-------------------------------------------------------------------------
-----(2)------------------------------------------------------------------
#include "stdafx.h"
#include <iostream>
using namespace std;
class MPointerList{
public:
int f(int a, int b){
return a * b;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
typedef int (* FUNC_POINTER)(int, int);
FUNC_POINTER fp;
//fp = f;
MPointerList mP;
fp = mP.f;
cout << fp(1,2) <<endl;
getchar();
return 0;
}
-------------------------------------------------------------------------
No.2ベストアンサー
- 回答日時:
(1) インスタンスメンバ関数は代入できない
既に回答がありますが、インスタンスメンバ関数のポインタは int (MPointerList::*)(int,int) という型であり、静的な関数のポインタ int (*)(int,int) とは異なる型です。そもそも、インスタンスメンバ関数を呼び出す時は引数 a, b だけでなく持ち主のオブジェクトインスタンス mP も必要なのです。その時の呼び出し方が、(mP.*memberFunctionPointer)(a,b) になる訳です。
(2) 静的メンバ関数は代入できる
因みに、インスタンスメンバ関数ではなく、静的メンバ関数のポインタは通常の関数ポインタと同じ型です。
呼出にオブジェクトインスタンスを必要としないためです。
--------------------
class MPointerList{
public:
static int f(int a, int b){
return a * b;
}
};
FUNC_POINTER fp = &MPointerList::f; // OK
--------------------
(3) オブジェクトインスタンスと一緒に取り扱う
「メソッド」と書いている辺り、C# のデリゲートや Delphi のメソッドポインタの様な使い方を期待していますか? (C++ ではメンバ関数の事をメソッドとは言わないので…。)
実は、デリゲートやメソッドポインタは、内部的には単なる関数ポインタではなく (オブジェクトインスタンスへの参照) と (メンバ関数へのポインタ) のペアです。C++ でも同様の事をしたければ、同じようにインスタンスへの参照とメンバ関数へのポインタのペアを取り扱う関数オブジェクトのクラスを用意すれば良いのです。
そして、C++11 でその様なクラスが標準ライブラリに追加されました。std::function です。Visual Studio 2010 以降など C++11 に (部分的に) 対応している最近のコンパイラで使えます (もちろん、古いコンパイラではコンパイルできないコードになってしまうという問題はありますが)。更に、C++11 のラムダ式と組み合わせればその様な関数オブジェクトの生成も簡単になります。
--------------------
#include <functional>
using namespace std;
int globalFunction(int a, int b){
return a * b;
}
class MPointerList{
public:
static int staticMemberFunction(int a, int b){
return a * b;
}
int instanceMemberFunction(int a, int b){
return a * b;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
std::function<int(int,int)> fp;
// もちろん、静的な関数は代入できる
fp = globalFunction;
// 静的なメンバ関数も代入できる
fp = &MPointerList::staticMemberFunction;
MPointerList mP;
// &MPointerList::f と mP への参照から関数オブジェクトを生成し、fp に代入できる
fp = std::bind(std::mem_fn(&MPointerList::instanceMemberFunction), std::ref(mP), std::placeholders::_1, std::placeholders::_2);
// ラムダ式を使えば、上と同等の事をより簡単に書ける。
fp = [&mP](int _1,int _2) -> int{return mP.instanceMemberFunction(_1,_2);};
cout << fp(1,2) <<endl;
getchar();
return 0;
}
--------------------
★注意★
mP の寿命に注意して下さい。変数 mP の寿命が尽きた後も、fp の中に mP への参照が残りますが、この時に fp を呼び出すと異常動作します。変数 mP のスコープの外で fp を使いたい場合には、MPointerList を動的に確保して寿命を管理する必要があります。その為には、C++11 の std::shared_ptr (~寿命自動管理機能付きポインタ) を使うと楽です。
--------------------
#include <memory>
中略
std::shared_ptr<MPointerList> mP2=std::make_shared<MPointerList>();
fp = [mP2](int _1,int _2)->int{return mP2->instanceMemberFunction(_1,_2);};
//※参照キャプチャ [&mP2] ではなく値キャプチャ [mP2]
--------------------
akinomyogaさん
とても詳しいご説明
大変有難うございました。
C++は本当に様々なことができるのですね。
自分も精進しようと思います。
No.1
- 回答日時:
> 関数ポインタに外部参照でメソッドを代入することは出来ないのでしょうか?
できません。
やるならこんな↓カンジ。
#include <iostream>
using namespace std;
class MPointerList{
public:
int f(int a, int b){
return a * b;
}
};
int main()
{
typedef int (MPointerList::* FUNC_POINTER)(int, int);
FUNC_POINTER fp;
fp = &MPointerList::f;
MPointerList mP;
cout << (mP.*fp)(1,2) <<endl;
getchar();
return 0;
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C++プログラミングコードにポリモーフィズムを取り入れ方を教えてください。 2 2023/06/09 11:17
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# C++初心者です stirng 2 2022/09/20 20:43
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# C言語の課題が出たのですが自力でやっても分かりませんでした。 要素数がnであるint型の配列v2の並 3 2022/11/19 17:41
- C言語・C++・C# C pointer? or... 2 2022/03/29 00:47
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
このQ&Aを見た人はこんなQ&Aも見ています
-
好きな人を振り向かせるためにしたこと
大好きな人と会話のきっかけを少しでも作りたい、意識してもらいたい…! 振り向かせるためにどんなことをしたことがありますか?
-
スマホに会話を聞かれているな!?と思ったことありますか?
スマートフォンで検索はしてないのに、友達と話していた製品の広告が直後に出てきたりすることってありませんか? こんな感じでスマホに会話を聞かれているかも!?と思ったエピソードってありますか?
-
【お題】逆襲の桃太郎
【大喜利】桃太郎が1回鬼退治に失敗したところから始まる新作昔話「リベンジオブ桃太郎」にはこんなシーンがある
-
【選手権お題その3】この画像で一言【大喜利】
とあるワンシーンを切り取った画像。この画像で一言、お願いします!
-
今から楽しみな予定はありますか?
いよいよ2025年が始まりました。皆さんには、今から楽しみにしている予定はありますか?
-
適切な変換関数が存在しない???
C言語・C++・C#
-
既定のコンストラクタがありません。というエラーについて
C言語・C++・C#
-
既定のコンストラクタがない?
C言語・C++・C#
-
-
4
静的でないメンバ関数の呼び出しが正しくありません
C言語・C++・C#
-
5
1 つ以上の複数回定義されているシンボルが見つかりました
C言語・C++・C#
-
6
配列の要素数に変数を入れたいときには
C言語・C++・C#
-
7
C++言語で、構造体のコピーは可能(しても良い)のでしょうか?
C言語・C++・C#
-
8
std::stringからLPCWSTR型への変換
C言語・C++・C#
-
9
CStringからchar*への型変換について教えてください。
C言語・C++・C#
-
10
char*を初期化したいのですが
C言語・C++・C#
-
11
<unistd.h>をVisualStudioでつかえるようにする
C言語・C++・C#
-
12
関数から配列を返すには?
C言語・C++・C#
-
13
VC++ 2008 EXPRESS _T"識別子がみつかりません"
C言語・C++・C#
-
14
fgetsなどのときのstdinのバッファを消すには?
C言語・C++・C#
-
15
cout と cerrの違い
C言語・C++・C#
-
16
変数名の付け方
Java
-
17
正負を反転させて出力するプログラム
C言語・C++・C#
-
18
deleteで開放するとエラーになる原因がわからない
C言語・C++・C#
-
19
Enterキーを押されたら次の処理に移るという事をしたい。
C言語・C++・C#
-
20
C++ で、「)」が必要 というエラー
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・「みんな教えて! 選手権!!」開催のお知らせ
- ・漫画をレンタルでお得に読める!
- ・【大喜利】【投稿~1/20】 追い込まれた犯人が咄嗟に言った一言とは?
- ・洋服何着持ってますか?
- ・みんなの【マイ・ベスト積読2024】を教えてください。
- ・「これいらなくない?」という慣習、教えてください
- ・今から楽しみな予定はありますか?
- ・AIツールの活用方法を教えて
- ・【選手権お題その3】この画像で一言【大喜利】
- ・【お題】逆襲の桃太郎
- ・自分独自の健康法はある?
- ・最強の防寒、あったか術を教えてください!
- ・【大喜利】【投稿~1/9】 忍者がやってるYouTubeが炎上してしまった理由
- ・歳とったな〜〜と思ったことは?
- ・ちょっと先の未来クイズ第6問
- ・モテ期を経験した方いらっしゃいますか?
- ・好きな人を振り向かせるためにしたこと
- ・【選手権お題その2】この漫画の2コマ目を考えてください
- ・【選手権お題その1】これってもしかして自分だけかもしれないな…と思うあるあるを教えてください
- ・スマホに会話を聞かれているな!?と思ったことありますか?
- ・それもChatGPT!?と驚いた使用方法を教えてください
- ・見学に行くとしたら【天国】と【地獄】どっち?
- ・これまでで一番「情けなかったとき」はいつですか?
- ・この人頭いいなと思ったエピソード
- ・あなたの「必」の書き順を教えてください
- ・14歳の自分に衝撃の事実を告げてください
- ・人生最悪の忘れ物
- ・あなたの習慣について教えてください!!
- ・都道府県穴埋めゲーム
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
「指定されたキャストは有効で...
-
C言語での引数の省略方法
-
【C++】関数ポインタの使い方
-
int型の変数値をバイト列として...
-
実数の整数部,小数部の取得
-
(int *)の意味
-
C言語 エラーの原因がわからな...
-
if と配列の組み合わせ
-
ラップ関数とはどんなものですか?
-
警告 W8065について。
-
#define _CRT_SECURE_NO_WARNIN...
-
複数桁10進数の*桁目だけを抽出...
-
任意の文字列のアルファベット...
-
windows-findstrの正規表現を使...
-
c言語の配列を使ってサイコロを...
-
C++でRPGを作成する際のステー...
-
中央値の抽出
-
C言語のサイコロシミュレート
-
C言語でlookupのような関数って?
-
キーボードから自然数を入力し...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
「指定されたキャストは有効で...
-
C言語での引数の省略方法
-
C言語 エラーの原因がわからな...
-
#define _CRT_SECURE_NO_WARNIN...
-
複数桁10進数の*桁目だけを抽出...
-
【C++】関数ポインタの使い方
-
ラップ関数とはどんなものですか?
-
ColorをRGBで指定する方法
-
(int *)の意味
-
足して100になるような乱数のア...
-
シェルピンスキーのギャスケット
-
if と配列の組み合わせ
-
実数の整数部,小数部の取得
-
構造体の勉強中です 合計点の高...
-
「{ } で囲むだけ」は正しい?
-
c言語の配列を使ってサイコロを...
-
式は定数値が必要です」という...
-
acceptをalarmでタイムアウトさ...
-
read関数をノンブロッキングで...
-
std::set<int> で、ある値が何...
おすすめ情報