
関数ポインタの使い方で悩んでいます。
下記の
(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も見ています
-
適切な変換関数が存在しない???
C言語・C++・C#
-
既定のコンストラクタがない?
C言語・C++・C#
-
静的でないメンバ関数の呼び出しが正しくありません
C言語・C++・C#
-
-
4
char*を初期化したいのですが
C言語・C++・C#
-
5
CStringからchar*への型変換について教えてください。
C言語・C++・C#
-
6
<unistd.h>をVisualStudioでつかえるようにする
C言語・C++・C#
-
7
既定のコンストラクタがありません。というエラーについて
C言語・C++・C#
-
8
1 つ以上の複数回定義されているシンボルが見つかりました
C言語・C++・C#
-
9
クラスのアドレスを引数として渡したい
C言語・C++・C#
-
10
文字列の切り出し
C言語・C++・C#
-
11
リソースエディタでスタティックテキストの文字サイズの変更
C言語・C++・C#
-
12
ハンドルはポインタか
C言語・C++・C#
-
13
C言語で、メモリを解放しないで終わるプログラム
C言語・C++・C#
-
14
変数名の付け方
Java
-
15
構造体のメンバをfor文で回したい
C言語・C++・C#
-
16
C++ で、「)」が必要 というエラー
C言語・C++・C#
-
17
deleteで開放するとエラーになる原因がわからない
C言語・C++・C#
-
18
構造体のextern方法
C言語・C++・C#
-
19
エラーの原因は?「この関数の定義が見つかりません」
C言語・C++・C#
-
20
std::stringからLPCWSTR型への変換
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
std::set<int> で、ある値が何...
-
C言語での引数の省略方法
-
#define _CRT_SECURE_NO_WARNIN...
-
C言語の演算子!=の使い方で質問...
-
C言語のポインタ
-
VC++の配列で
-
複数桁10進数の*桁目だけを抽出...
-
「指定されたキャストは有効で...
-
C言語/ランダムbeepのプログラ...
-
プログラミングについてです。
-
プログラムのどこがエラーか教...
-
リストに整数値があるか判定す...
-
memsetについて
-
c言語 ファイル出力について
-
エンキューとデキューの操作関数
-
switch case 文 でお願いしま...
-
VCの構造体【否 .Net】文字列
-
うまくいかないorz
-
C言語プログラム能力検定の問題...
-
C言語の簡単な質問です。
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
「指定されたキャストは有効で...
-
C言語での引数の省略方法
-
#define _CRT_SECURE_NO_WARNIN...
-
複数桁10進数の*桁目だけを抽出...
-
ラップ関数とはどんなものですか?
-
C言語 エラーの原因がわからな...
-
(int *)の意味
-
【C++】関数ポインタの使い方
-
if と配列の組み合わせ
-
構造体の勉強中です 合計点の高...
-
windows-findstrの正規表現を使...
-
C言語で分からないところがあり...
-
int型の変数値をバイト列として...
-
PowerShellがうまくいかない
-
C言語での奇数の和
-
「{ } で囲むだけ」は正しい?
-
std::set<int> で、ある値が何...
-
実数の整数部,小数部の取得
-
エラー 添字が付けられた値が、...
-
int16_t の _t は何?
おすすめ情報