関数のポインタを返すメンバ関数 – 固定ページ 2 – プログラミング – Home

関数のポインタを返すメンバ関数
 
通知
すべてクリア

[解決済] 関数のポインタを返すメンバ関数

固定ページ 2 / 2

ガラ
 ガラ
(@ガラ)
ゲスト
結合: 20年前
投稿: 201
Topic starter  

maruさん、bunさん、Blue さん、tetrapodさん、仲澤@失業者さん、hirocco さん、レ
スありとうございます。

maruさん
>std::map<std::string, ddfunc_type*> func_table;
なるほど、いい手ですね。検討してみます。

bunさん、
>double (*myclass::myfunc(char const *))(double) { ... }
ありがとうございます。理解できたような気がします。
double (*p)(double)myclass::myfunc(char const *) {...}
ってこんなことしてました。

tetrapodさん、
>C/C++ のポインタ関連の記述方法は不必要に複雑/煩雑な上に、この例は
>typedef を使って1段階簡単にしてやるととても読みやすくなる典型なわけで
>あえてプレーンな書き方をせずに typedef したものにしておく・・・

同意させていただきます。

>typedef double ddfunc_type(double);
>ddfunc_type* myclass::myfunc(const char* p) { ... }
で動作しましたが、ついでに変数もこのtypedef で
ddfunc_type * func ;
とやってみましたが、コンパイルエラーがでます。関数の宣言のみに使える?というの
は、なんともわたしの今までもっていた'typedef'のイメージと全然ちがいます。
でも現実的にはこの表現にすることを選択すると思います。

仲澤@失業者さん、
>「よくわからないときは無視してよい」という考え方は多くの場合、誤りです(vv;)。
おっしゃるとおりですね。すいません。すぐわからないとほっといてしまいます。

hirocco さん、
>私は基本的にできるだけ複雑にしない派ですねぇ
>後で自分でも読めなくなっちゃうんで。。。
わたしも、’簡単にする派’です。そのときは、集中しているので、いろいろ考え付き
ますが、あとで見たとき、わからなくなるのは、つらいですから・・・

PS)tetrapodさん、この課題ちょっとまってくださいませ。
(わたしも、うら若き?なので、食事の支度をしなければ・・)
>ぢゃあここで課題
>・関数ポインタのテーブル functable (bun 氏の Func[]) を記述して味噌
>・POSIX の signal 関数は void (*signal(int, void (*func)(int)))(int); という
 プロトタイプ宣言される。解読して味噌。 typedef を使って簡単にして味噌。


返信引用
ガラ
 ガラ
(@ガラ)
ゲスト
結合: 20年前
投稿: 201
Topic starter  

tetrapodさん、課題への解答。これでいいですか?

static double (*functable) (double)[FV_Last] ;
functable[FV_SIN] = sin ;
functable[FV_SIN] = cos ;
functable[FV_SIN] = tan ;

void (*signal(int, void (*func)(int)))(int); ということは、
第一引数がint型で
第二引数が「int型の引数ひとつ、返り値なしの関数」のポインタ

返り値が「int型の引数ひとつ、返り値なしの関数」のポインタ
の名前がsingalという関数なので、

typedef void vifunc_type (int) ;
vifunc_type *signal(int,vi_func_type *) ;


返信引用
ガラ
 ガラ
(@ガラ)
ゲスト
結合: 20年前
投稿: 201
Topic starter  

ちょっと訂正します。
enum TFunc {
FV_SIN=0,
FV_COS,
FV_TAN
} ;
static double (*functable) (double)[FV_Last] ;
functable[TFunc::FV_SIN] = sin ;
functable[TFunc::FV_COS] = cos ;
functable[TFunc::FV_TAN] = tan ;


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

signal の方は正解。
functable のほうは不正解。自分でコンパイラに食わせてみた?エラーになるはず。

もう少し考え方のヒントを

C / C++ の変数宣言を typename variablename; と考えちゃダメ。
typename arrayname[elementcount]; と考えちゃダメ。
型は変数名の前後にわたって書かれることがある。

identifier( のように名前+開き丸カッコがあると、その名前は関数名
identifier[ のように名前+開き角カッコがあると、その名前は配列名
今、「関数へのポインタ」の配列を作ろうとしているわけだ。
なので、この配列変数の宣言の際には functable[要素数] という記述が必ず現れる。
ここで気をつける点は
・名前と角カッコは場所が分離しない。
・カッコ(丸、角)の後ろに何か文字が来ることは、ごく当たり前。

double (*functable[3])(double); // が正解。

> ddfunc_type * func ;
はできるはずだが。ウチではコンパイルエラーにならないし。
ddfunc_type f; はダメだけど。


返信引用
ガラ
 ガラ
(@ガラ)
ゲスト
結合: 20年前
投稿: 201
Topic starter  

tetrapod さんレスありがとうございます。
ここのところは、違和感があったところなので、ご説明いただいて、
たいへんうれしく思います。
>C / C++ の変数宣言を typename variablename; と考えちゃダメ。
>typename arrayname[elementcount]; と考えちゃダメ。
>型は変数名の前後にわたって書かれることがある。

>identifier( のように名前+開き丸カッコがあると、その名前は関数名
>identifier[ のように名前+開き角カッコがあると、その名前は配列名
>今、「関数へのポインタ」の配列を作ろうとしているわけだ。
>なので、この配列変数の宣言の際には functable[要素数] という記述が必ず現れる。
>ここで気をつける点は
>・名前と角カッコは場所が分離しない。
>・カッコ(丸、角)の後ろに何か文字が来ることは、ごく当たり前。

理解する上で、たいへん大きなコメントとなりました。
ありがとうございました。
ひとまず、解決とさせていただきます。

PS’現在、hirococoさんのご指摘のあったとおり、関数名を文字列にせず、enumでの
宣言コンスタントに変えているところです。

PS’他のみなさんもありがとうございました。


返信引用
ガラ
 ガラ
(@ガラ)
ゲスト
結合: 20年前
投稿: 201
Topic starter  

結局、switchにしちゃいました。maruさん、が書いてくださった、C標準ライブラリーの
mapを使うのもいいんですが、ユーザ定義関数も視野にいれると、この書き方がいちば
ん、あとで広げやすそうなので、そうしました。みなさん、ご意見、ご指導、ありがと
うございました。

switch(Sc2){
case CSToken::SSyntacticCategory2::SC2_SIN:
AnsData = sin(dData[0]) ;
break ;
case CSToken::SSyntacticCategory2::SC2_COS:
AnsData = cos(dData[0]) ;
break ;
case CSToken::SSyntacticCategory2::SC2_TAN:
AnsData = atan(dData[0]) ;
break ;
             :
             :


返信引用
固定ページ 2 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました