忍者ブログ

神戸電子専門学校ゲームソフト学科の生徒が運営するGESのブログです。

   

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

関数オブジェクト(ファンクタ)

3年生では、もう早期出社でいなくなっていく人がいます。
夏休み明けから、11月始めから、冬休み明けから。
時期は様々ですがいなくなります。寂しいです。

関数オブジェクトについて展開していきます。
これらを知ることで for_each  を利用できるようになります。


拍手[0回]




 

*説明*
 
()演算子を定義したものを関数オブジェクト(ファンクタ)と呼びます。
この説明ではよく分からないので実際に書きます。
 
#include <stdio.h>
class MyCls
{
public:
// 普通の関数
void func(){puts("func");}
// 引数なし関数オブジェクト
void operator()(){ puts("operator"); }
// 引数あり関数オブジェクト
void operator()(const char* _str){ puts(_str); }
};
void main()
{
MyCls obj;
obj.func();
obj(); // ☆1
obj("893"); // ☆2
}
 
---出力---
func
operator
893
----------
 
☆1や☆2でメンバ変数を指定しないでそのまま()を付けることで、
中の関数を呼び出す事ができます。
メンバ関数の名前が分からなくても呼べる所に魅力があります。
 
関数オブジェクトを引数に取る関数が標準ライブラリにありますが、
各関数によって関数オブジェクトの戻り値や引数の数が指定されています。
std::for_eachはひとつの引数をとる関数オブジェクトを指定します。
std::sortは二つの引数をとり、戻り値がboolの関数オブジェクトを指定します。
などがあります。
 
std::for_eachを例にサンプルを示します。
#include <stdio.h>
#include <algorithm>
#include <list>
class MyCls
{
public:
void operator()(int i){printf("%d",i);}
};
 
void main()
{
std::list<int> int_list;
for( int i=0 ; i<10 ; i++ )
{
int_list.push_back( i );
}
std::for_each( int_list.begin(), int_list.end(), MyCls() );
}
---出力---
0123456789
----------
 
*std::for_eachと同じ関数*
この関数はstd::for_eachと全く同じ振る舞いをする関数です。
template<class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f)
{
    for (; first != last; ++first) {
        f(*first);
    }
    return f;
}
f(*first);について見ていきます。
fはMyClsの変数です。
f( イテレータの中身 );とすることで関数オブジェクトが呼ばれています。
どんな型がきても関数オブジェクトを呼べばいいので、
メンバ関数の名前に左右されません。これが関数オブジェクトのいい所です。

*補足*
std::for_eachにint_list.begin(),int_list.end()と毎回書くのが面倒なので、
関数テンプレートを作ると、
template<class ConType,class FuncType>
void for_each(ConType& _con,FuncType _func)
{
for_each( _con.begin(), _con.end(), _func );
}
上のサンプルを使ってこの関数を呼び出すには
for_each( int_list,Mycls() );
などのように小さくまとめれる事も可能です。
 
 
*実例*
こういうよくあるプログラム
std::list<CEnemy*>::iterator it;
for( it=m_list.begin() ; it=m_list.end() ; ++it)
{
(*it)->Update();
}
for_each(m_list, boost::mem_fn(&CEnemy::Update) );
に一行で書けます。
(mem_fnについては次回説明しますがメンバ関数から関数オブジェクトを生成します。)
 
 
関数オブジェクトについては以上です。
 
次回の記事で標準関数である
count count_if find などを使えるような知識を書きます。
実際の内容は
mem_fun---メンバ関数から関数オブジェクトを生成
bind----------メンバ関数から引数を指定して関数オブジェクトを生成
 
などを記事にしようと思っています。
ここまで読んで頂きありがとうございます。

byリーダ和田
PR

COMMENT

NAME
TITLE
MAIL(非公開)
URL
EMOJI
Vodafone絵文字 i-mode絵文字 Ezweb絵文字
COMMENT
PASS(コメント編集に必須です)
SECRET
管理人のみ閲覧できます

ブログ内検索

最新コメント

[01/29 人面犬]
[10/01 8ch]
[09/12 uncle]
[09/10 某卒業生]
[06/07 uncle]

カレンダー

10 2024/11 12
S M T W T F S
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

テスト

Copyright ©  -- GESブログ --  All Rights Reserved
Design by CriCri / Photo by Geralt / powered by NINJA TOOLS / 忍者ブログ / [PR]