【C言語/C++】関数ポインタと関数オブジェクトを使ってみる

公開日: : 最終更新日:2014/08/14 C/C++

スポンサーリンク

関数ポインタを使う

関数ポインタはポインタの一種で文字通り関数のポインタの事で、関数を遠隔操作できるようになる文法です。たぶんほとんどの場合関数の引数として使うんじゃないかと思うのでそれだけ紹介します。

#include<stdio.h>
int add(int a,int b){
	return a+b;
}
int sub(int a,int b){
	return a-b;
}
//関数ポインタを使っている
int calc(int (*func)(int,int),int a,int b){
	return func(a,b);
}
int main(void){
	int x = 10;
	int y = -4;
	int ans1 = calc(add,x,y);	//足し算をしている
	int ans2 = calc(sub,x,y);	//引き算をしている
	printf("%d,%d\n",ans1,ans2);	//6,14が出力される
	return 0;
}

関数ポインタを関数の引数とするには

戻り値の型 (*名前)(引数の型)

とすればできます。名前は適当で構いません。この引数で指定される関数は後から折り返し呼ばれるためコールバック関数と言われています。

こういった関数ポインタの使われている例としてOpenGLなどが挙げられます。OpenGLではライブラリ側で大まかな骨組みと関数を提供し、表示などの個別の処理は自分で作った関数をコールバック関数として登録させることで動くイベントドリブン形式になっています。

この例ではcalcという関数の引数に関数のポインタを設定しています。これにより、指定した戻り値と引数が同じ関数をその引数に代入して実行することができます。

ここでは単純に足し算引き算してるだけですが、利点としては動的に処理を変更できるという所にあります。オブジェクト指向の多態性の部分に相当していると思います。

関数オブジェクト

C言語であれば関数ポインタを使えばいいのですが、C++であれば関数オブジェクト(ファンクタ)を使う方がいいといわれています。関数オブジェクトとは文字通り関数をオブジェクトとしたものです。例を見た方が早いと思うので下を見てください。

#include<stdio.h>
class Add
{
public:
	//関数オブジェクト
	int operator()(int a,int b){
		return a+b;
	}
};
class Sub
{
public:
	//関数オブジェクト
	int operator()(int a,int b){
		return a-b;
	}
};
int main(void){
	int x = 10;
	int y = -4;
	Add add;
	Sub sub;
	int ans1 = add(x,y);	//足し算をしている
	int ans2 = sub(x,y);	//引き算をしている
	printf("%d,%d\n",ans1,ans2);	//6,14が出力される
	return 0;
}

ここでは説明しませんがoperatorというのは演算子のオーバーロードというC++の文法です。

やっていることは関数ポインタの例と同じですが、それとの大きな違いはなんといっても変数を持てるということで、関数のようにふるまいながらも状態を保持することができるという所にあります。(この例ではその利点が発揮されていません。すいません。)

例えば動的に取得されるデータをコンストラクタなどで渡してそれに応じた結果を返すというようなことができてしまうわけです。(たぶんもっと賢い使い方があると思います)

また、テンプレート関数と組み合わせることでこういった使い方もできます。

#include<stdio.h>
class Add
{
public:
	//関数オブジェクト
	int operator()(int a,int b){
		return a+b;
	}
};
class Sub
{
public:
	//関数オブジェクト
	int operator()(int a,int b){
		return a-b;
	}
};
//テンプレート関数
template<class Functor>
int calc(int a,int b,Functor f){
	return f(a,b);
}
int main(void){
	int x = 10;
	int y = -4;
	Add add;
	Sub sub;
	int ans1 = calc(x,y,add);	//足し算をしている
	int ans2 = calc(x,y,sub);	//引き算をしている
	printf("%d,%d\n",ans1,ans2);	//6,14が出力される
	return 0;
}
スポンサーリンク
Amazon
  • このエントリーをはてなブックマークに追加

関連記事

フォルダ画像

【C言語/C++】フォルダ作成を行う

C言語、C++でフォルダを作成するには『direct.h』にある『_mkdir』関数を使うことで実現

記事を読む

LIG_h_dartssurudansei500-thumb-500xauto-3336

OpenCVで矢印を描画する

OpenCVで矢印を描画するという関数が無いみたいだったので作りました。書いていることは参考リンク先

記事を読む

no image

【C++】既に main.obj で定義されています

error LNK2005: 既に main.obj で定義されています。 fatal error

記事を読む

CSS85_keywosousasruop20131019500-thumb-500xauto-4249

【C言語/C++】配列をシャッフルしてランダムに入れ替える

C言語・C++で配列をシャッフルする方法 Fisher–Yatesシャッフルアルゴルズムにより配列

記事を読む

darts-102919_640

【C++】多次元ベクトルクラスを作る

3次元ベクトルクラスや2次元ベクトルクラスを作るときは内部のデータとして静的な配列を使えば問題ありま

記事を読む

0533f0e24573da8dbd68f5c6e7d452d7_s

【C++】ファイルの読み込みまとめ

C++におけるファイル読み込みのまとめ ファイルの開き方 値の取得方法 >>演算子

記事を読む

PAK23_husentomemo20140313500-thumb-500xauto-4376

【C言語】printfのような関数を作る

C言語でよくつかわれるprintfでは例えば int a,b,c; … printf(

記事を読む

PAK15_notepenhikkiyougu20140312500-thumb-500xauto-4327

【C言語/C++】fgetsを使ってファイルを読み込む

fgetsで単純にファイルを読み取る C言語、C++でfgetsを使ってファイルを読み込む方法です

記事を読む

PAK86_codeing20140517500-thumb-500xauto-4601

【C言語/C++】余りを求める剰余演算子(%)を使う

基本的なことかもしれませんが、C言語やC++などであまりを出すには剰余演算子である『%』を使います。

記事を読む

caa1

【C言語/C++】コンソールでAAアニメーション

コンソール上でAA(アスキーアート)のアニメーションをさせます。 手順としては

記事を読む

encodingtype
【PHP】headerでContent-Typeを指定したのに効かない場合の対処法

PHPでサイトマップを作ろうと思い、XML形式のファイルを出力しようと

_rtm0919_tp_v
スマホ向け幅固定サイトの回転時の幅対応方法

幅固定サイトでのスマホ回転時Webサイトの横幅を合わせる方法のメモ。

rssimage
【PHP】特定のURLからそのAtomやRSSのフィードを抽出する方法

特定のURLからRSSやATOMのフィードを抽出する方法をメモ。 流

rssimage
フィード抽出ツール(RSS1.0、RSS2.0、atom)

任意URL サイト名 サイトURL RSS1.0

computer_server
格安プラン限定レンタルサーバー機能比較表(2016年)

はじめに  最近新しい共用サーバーをレンタルしようと思い調査およびそ

school_toshokan_hondana
kindle unlimitedが便利だったのでお勧めの使い方など感想メモ

 kindle unlimitedというサービスが8/3からAmazo

TAKEBE055122558_TP_V
寝る前にスマホを見ると斜視になる可能性とその対策

はじめに  寝る前などスマホを横になりながら見続けると斜視になる可能

→もっと見る

  • Author : ががんぼ
    プログラミングやWeb関係で気付いたことについてメモしていく予定。だいたいが備忘録ですが、自分でサンプルを作って動かしてみたりしています。
PAGE TOP ↑