関数のポインタを返すメンバ関数 – プログラミング – Home

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

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

固定ページ 1 / 2

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

MFC VC++6.0、XP

関数のポインタを返す、メンバ関数を作りたいのですが、コンパイルエラーがでてしま
います。どうすればいいのでしょうか?
double (*p) (double) CSParser::GetFunctionPointerDouble1 (const LPCSTR
&lpszFunctionName) //この行でエラーがでる
{
if (!strcmp( lpszFunctionName,sin)) {
return(sin) ;
}
return(cos) ;
} ;

エラー::error C2629: 'double (' は不正です


引用未解決
トピックタグ
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

とりあえず typedef を使うと簡単。
下記の typedef が何を宣言しているのか理解できる?

typedef double ddfunc_type(double);
ddfunc_type* myclass::myfunc(const char* p) { ... }

理解できたら typedef を使わない記述方法を *自分で* 模索してみるといい。

(strcmp しまくるのは非常に遅いので実用に供する前に再考慮)


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

tetrapodさんの言うとおり「関数名」でスイッチするのは
やめたほうが良いかも。んで、以下にサンプル。

#include <math.h>
typedef double ( __cdecl *TriFunc)( double _X);
TriFunc TriFunc_Get( int Type)
{
switch( Type){
default:
case 0: return sin;
case 1: return cos;
case 2: return tan;
}
}
void foo()
{
double d = TriFunc_Get( 1)( double( 0)); // cos(0)
}


返信引用
hirocco
 hirocco
(@hirocco)
ゲスト
結合: 14年前
投稿: 138
 

深く考えないで,意外ととこうでもよかったりして。。。

double CSParser::三角関数Function(int type,double value)
{
double dblResult =0.0;

switch( type ){
default:
case 0: dblResult =sin(value);
case 1: dblResult =cos(value);
case 2: dblResult =tan(value);
}
return dblResult;
};

おっと,関数ポインタの勉強にはなりませんね


返信引用
hirocco
 hirocco
(@hirocco)
ゲスト
結合: 14年前
投稿: 138
 

あ,breakを忘れてますね。。。


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

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

tetrapod さんの記述をそのまま引用すると、やりたいことは、できたのですが、
typedef を使わない形がよくわかりません。

仲澤@失業者さんの書いてくださった、__cdecl は、特に必要ないのかな?と考えてい
ます。(マニュアルを読んだのですが、コンパイラオプションがどうのこうので、よく
わかりません。)


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

hiroccoさんレスありがとうございます。
実際はCEditCtrlに入力された文字を計算するので、文字比較は、必要なのですが、
double CSParser::三角関数Function(int type,double value)
{
double dblResult =0.0;

switch( type ){
default:
case 0: dblResult =sin(value);
case 1: dblResult =cos(value);
case 2: dblResult =tan(value);
}
return dblResult;
};

でいいかな?という気がします。いや、このほうがいいかな?とも・・
実際にはmath.hのライブラリをほとんどサポートするつもりで、

pRetDArgumentD CSParser::GetFunctionPointerRD_AD (const LPCSTR
&lpszFunctionName) const
{
static struct SFunctionArgument1 {
char Name[FUNCTION_NAME_MAX];
double (*FunctionPointer) (double) ;
} FunctionArgument1[] = {
{sin,sin},
{cos,cos},
{tan,tan},
{asin,asin},
{acos,acos},
{atan,atan},
{sqrt,sqrt},
{log,log},
} ;

int i,i_max = sizeof(FunctionArgument1)/sizeof(SFunctionArgument1) ;
for (i = 0;i < i_max;i++) {
if(!strcmp(lpszFunctionName,FunctionArgument1[i].Name)) {
return(FunctionArgument1[i].FunctionPointer);
}
}

return((pRetDArgumentD)NULL) ;
}
とこんな感じにしているのですが・・・う~ん、考えどころですね。


返信引用
hirocco
 hirocco
(@hirocco)
ゲスト
結合: 14年前
投稿: 138
 

でもね,sinはdoubleだけじゃないのよねぇ

あと,ここからは私の勝手な考えですけど,
やっぱり仲澤@失業者さんが言う通りインデックス?フラグ?で分けたほうがいいと思
いますよ
で,defineなりenumで定義しとくと後で絶対楽だから

そして,字句解析が必要ならその前段で解析させて,そのインデックス?フラグ?を調べ
て,渡すだけ
そうしておけば,字句解析を伴わない場面でもそのメソッドはまた有用になると思います
字句解析のモジュールと実際の計算するモジュールと別に設計したほうが綺麗かなぁっ
てね
ΣとかΠとか∫とか絡んでくると分けてないと私は頭おかしくなっちゃいますねwww

>math.hのライブラリをほとんどサポート...
引数の型も数も違うのとかありますけど。。。


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

hirocco さん、レスありがとうございます。

字句解析は、いれてありますが、関数名は、文字列のままです。
将来的に、ユーザ定義関数をいれようと思っているので、そうしたほうがいいかも?
と思ってそうしています。(といっても心はゆれていますが・・)

>でもね,sinはdoubleだけじゃないのよねぇ
long doubleのことをおっしゃってるのと思うのですが、ユーザから見て、sin()一つを
long double で使えると、いいかな?と思っています。

もし、文字列のままだと、case文の代わりにstrcmp()のような比較関数がずらずら並ぶ
ということになるのですね・・・。う~ん。どうしようなぁ・・・


返信引用
maru
 maru
(@maru)
ゲスト
結合: 17年前
投稿: 358
 

> もし、文字列のままだと、case文の代わりにstrcmp()のような比較関数がずらずら並

> ということになるのですね・・・。う~ん。どうしようなぁ・・・
だったら連想配列を使ってみるのは如何でしょうか?
std::map<std::string, ddfunc_type*> func_table;
最初に初期化が必要ですが、アクセスはある程度早くなるでしょう。
(実際には計測していないので効果のほどは...)
もっとも、文字列比較がどの程度性能に影響があるかは疑問です。
確かに
> (strcmp しまくるのは非常に遅いので実用に供する前に再考慮)
には同意しますが、全体のバランスが重要。一連の処理が0.1秒で終わるものなら
それほど気にすることはないと考えます。
だからこそ、「再考慮」と言われているのだと思いますが。

字句解析があるのならば、その時点で記号化しておくほうが効率はいいでしょうね。
(仲澤@失業者さんの意見と同様)
ただし、私なら、switch / case 文ではなく表引きにします。


返信引用
bun
 bun
(@bun)
ゲスト
結合: 24年前
投稿: 761
 

あくまで私の考え方ですが、
文字列必須なら、連想配列(std::mapなど)を利用して検索した方がいい。

文字列必須じゃなく、分かりやすく区別したいだけならenumがお勧め。

enum FuncVal
{
FV_sin,
FV_cos,
FV_tan,
FV_Last // <- 最終要素
};

typedef double (*FunctionPointer)(double);

FunctionPointer Func[FV_Last];
Func[FV_sin] = sin;
Func[FV_cos] = cos;
Func[FV_tan] = tan;

こうすれば、添え字アクセスで検索の必要がない。
デバッグ時も添え字の値が 0, 1, 2 じゃなく、FV_sin, FV_cos, FV_tanなの
で分かりやすい。


返信引用
Blue
 Blue
(@Blue)
ゲスト
結合: 20年前
投稿: 1467
 

>typedef を使わない形がよくわかりません。

>typedef double ddfunc_type(double);
>ddfunc_type* myclass::myfunc(const char* p) { ... }

double (*myclass::myfunc(char const *))(double) { ... }

ちなみに、文字列比較時に英大小文字の違いは有になるのでしょうか?
まぁ、map使うにせよ、比較前に小文字に変換して、小文字同士で比較するだけですけど。


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

C/C++ のポインタ関連の記述方法は不必要に複雑/煩雑な上に、この例は
typedef を使って1段階簡単にしてやるととても読みやすくなる典型なわけで
あえてプレーンな書き方をせずに typedef したものにしておく・・・
というのは選択肢の1つとして「あり」だと思う。

字句的書き方講座
・ classname::funcname はこれで1つの名前なので分かち書きしない
・ふつーに 記述したときに [名前] が入るところが置き換わる
・引数のカッコと結合順を変えるカッコを区別する

double myfunc(float) /// 関数 myfunc あえて引数は float としておく
double (*myfuncptr)(float) /// 変数 myfuncptr は、関数へのポインタ
// 上記で (float) は引数のカッコ
// double *myfuncptr(float) とすると 引数のカッコは myfuncptr にくっつくので
// 先に *myfuncptr を評価させるためには別カッコが必要
double (*myfuncgetter(int))(float) /// 関数 myfuncgetter は関数ポインタを返す

// float の後ろに 変数名がいらないことに注目
double (*myclass::myfuncgetter(int funcno))(float) {
return functable[funcno];
}

ぢゃあここで課題
・関数ポインタのテーブル functable (bun 氏の Func[]) を記述して味噌
・POSIX の signal 関数は void (*signal(int, void (*func)(int)))(int); という
 プロトタイプ宣言される。解読して味噌。 typedef を使って簡単にして味噌。


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

>仲澤@失業者さんの書いてくださった、__cdecl は、特に必要ないのかな?と考えてい
>ます。(マニュアルを読んだのですが、コンパイラオプションがどうのこうので、よく
>わかりません。)

「よくわからないときは無視してよい」という考え方は多くの場合、誤りです(vv;)。

typedef を使わない書き方を「練習」してみるのは良いことです。
tetrapodさんの秀逸な説明をよく読んでやってみてください。

ですが、すぐにいやになると思います。特にtemplate<>が絡むと最悪で、
そういったソースを見ると、書いた人の「おつむのでき」に驚嘆します(笑い)。


返信引用
hirocco
 hirocco
(@hirocco)
ゲスト
結合: 14年前
投稿: 138
 

あったまいい人はありえないくらいあったまいいですもんね

私は基本的にできるだけ複雑にしない派ですねぇ
後で自分でも読めなくなっちゃうんで。。。

でも,練習というよりパズル感覚でいけば楽しいかもねぇ
私も趣味だったらハマル派です

でも,お仕事以外はパーソナルコンピュータなんて見たくもない


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

返信する

投稿者名

投稿者メールアドレス

タイトル *

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