初歩的な質問なのですが、
関数とメソッドの違いが分からず悩んでいます。
書籍や人によって、
関数とメソッドは同じ物として書いている物もあれば、
メソッドはクラスに関連付いた関数としていたり、
クラスでもpublic関数だけとか、
引数のある物がメソッド、
逆に無い物がメソッド等々…で、
どれが正しいのか良く分からないのです。

関数とメソッドの違いを教えていただけますよう、
お願いいたします。

このQ&Aに関連する最新のQ&A

A 回答 (14件中1~10件)

正解だけ先に言っておきましょう。

オブジェクト指向での定義は
「メソッドとは、オブジェクトに送られてきたメッセージを処理するモノ」
「関数とは、メソッドの実装」
ついでに、
「メッセージとは、オブジェクトに何かしらお願いするために送られるモノ」
です。メッセージとメソッドと関数は明確に違うのですよ。


上記の通りなんですが、質問の文について、なにが正しいか、という解答は「文脈による」としか言いよ
うが無いんです。
解説書の一部分だけ抜き出して考えるのは非常に危険な行為です。
文脈を色々変えてみます。例えばオブジェクト指向の話をしているとしたら、

>1. 関数とメソッドは同じ物として書いている物もあれば、
バツ。意味的に全く異なります。
'\0'と""とNULLと0くらい違います。等価なんていってしまったら石が飛びます。(私が投げます:-p)

> 2.メソッドはクラスに関連付いた関数としていたり、
サンカク。C++での実装はそうでしょうが、オブジェクト指向を考える上で、その考え方は危険です。

> 3.クラスでもpublic関数だけとか、
> 引数のある物がメソッド、
> 逆に無い物がメソッド等々…で、
バツ。引数の数でメソッドで無くなる?そんなバカな!
例えprivateでもメソッドですよ。


オブジェクト指向言語C++のことを考えよう!という文脈ならば、
1.サンカク。実装は確かにそうなってます。ですが、上記の通り意味的に違うんです。
2.○。C++において、メソッドは「クラスに関連ついた関数」として実装されてます。
3.そんなわけないでしょう。

オブジェクト指向?なにそれ?構造体に関数がくっついただけでしょ?と乱暴極まりない文脈なら、
1.○。当然!
2.なにいってるの?
3.サブルーチンとファンクションの違いだ!


と、文脈で全然変わるんですよ。これに関しては、本一冊だけだとなかなか気付きにくいです。
是非とも多数の本を読み比べることをお勧めします。
    • good
    • 0
この回答へのお礼

ご返答ありがとうございます。
うーん、文脈で意味する所が変わってしまうのか…
単純な事かと思っていましたが、
意外と複雑な事だったようで。
皆様方のご意見とても為になりました。

お礼日時:2005/04/18 10:03

ちなみに、メソッドの実装は、必ずしも関数コールである必要はありません。



C++ や Java の実装がそうなっているというだけの話で、それ以外の実装になっている言語もあるでしょう。
# 実装レベルの話は、C++ と Java の話しか知らないものでして。。。
# たとえば、Smalltalk とか Objective-C とか Ruby なんて言語は
# どうなんでしょうか。

…と、なんだか結局のところ、jacta さんと同じことを繰り返してるような気がしてきました。。。
# No5 あたりで。
    • good
    • 0

No11 ency です。



ちょっと補足しておきます。

オブジェクト指向は、あるクラスのインスタンスを必要なときに動的に生成できるわけで、その各インスタンスに対して個別に何か処理をさせるのがメソッドなわけで。。。

ただ、実は C でも似たようなことは普通にやっているわけで。。。

------------------------------------------------
#define SIZE 10

FILE *fp1, *fp2;
char buf[SIZE];

fp1 = fopen( "hoge1.txt", "r" );
fp2 = fopen( "hoge2.txt", "r" );

fgets( buf, SIZE, fp1 );
fgets( buf, SIZE, fp2 );
------------------------------------------------

たとえば、これをこんなふうに書替えれば、なんとなくオブジェクト指向っぽくなりませんかねぇ?
(注)こんな言語はありません。

------------------------------------------------
#define SIZE 10

FILE *fp1, *fp2;
char buf[SIZE];

fp1 = new FILE( "hoge1.txt", "r" );
fp2 = new FILE( "hoge2.txt", "r" );

fp1.fgets( buf, SIZE );
fp2.fgets( buf, SIZE );
------------------------------------------------

ま、fopen() が new FILE になってオブジェクト生成っぽくなっているところは置いといて、その下。。。
最後の引数を、関数の前にもっていって変数と関数をドットでつないだだけ。。。

ま、メソッドなんて、乱暴な言い方をすればこんなものです。

あ、でも、これがすべてだと思わないでくださいね。
今後のオブジェクト指向の勉強にさしさわりがありますので。。。
あくまで、導入部分のイメージとしてとらえてください。
# しかも実装ベースの話なので、オブジェクト指向の本来の考え方とは
# 違う部分もありますし。。。
# オブジェクト指向は、こんな実装ベースの話からスタートしているのではなく、
# もっと上位の概念というか、抽象的なところからスタートしている話です。
# ですので、メソッドと関数も、考えているレベルというかレイヤというかが
# 違っているわけですね。
# 外部設計レベルの話がメソッドであるとするならば、それに対する実装を
# 設計する内部設計レベルの話が関数ということになりますかねぇ。。。
# だから、本来、同じとか違うとかいうような比較は、あまり意味がないのかも
# しれません。

それにしても、こう考えると、メソッドを関数コールで実装している言語がある理由もなんとなくわかりませんか?
    • good
    • 0

関数とメソッド、参照とポインタ…議論が平行線になる話題ですね。



私の理解としては「メソッドの実装として関数コールで機能を実現している言語がある」というところですね。

C++ では、メソッド相当の機能を「メンバ関数」と呼んでいるだけだと思っています。
Java のメソッドも、内部では関数コールで実現しているだけだと思いましたが違いましたっけ?

ま、このせいで C++ や Java は純正オブジェクト指向として認めない人たちもいると聞いたことがあります。

で、私の結論としましては次のとおりです。

1. メソッドはオブジェクトに対するメッセージ送信に対する応答。
2. メソッドの実装方法の一つとして関数コールで実現している言語がある。

もっと乱暴な言い方をすれば、「メソッド=関数」という理解でとりあえずは良いのではないでしょうか。
特に C からオブジェクト指向に移行する人たちは、まずはこの理解で良いと思います。

結局「なんだ、メソッドって関数コールじゃん!」っていう結論になることが多いようです。

# 「メッセージを送信して…」などという言葉があると、「スレッドが変わるのか?」
# などという誤解をする人たちもいるようなので。。。
    • good
    • 0
この回答へのお礼

ご返答ありがとうございます。
皆様方のご意見とても為になりました。

お礼日時:2005/04/18 10:03

> 元々メソッド(method)というコトバはSmalltalkで用いられたものではなかったかしら。



歴史的経緯はどうであれ、SmalltalkでもJavaでもC#でも、そこで使われている「メソッド」はC/C++から見れば他言語の概念に過ぎません。

#7 の回答のように、その言葉を使っている人と、今自分が扱っているものから判断するしかないと思います。

実際、FA機器を扱ったりしていると、顧客が使う「メソッド」は生産手法のことだったりするわけで、そこで開発するアプリケーションでもやはり「メソッド=生産手法」になるわけです。
というわけで、C/C++とは直接関係のない用語の定義を一意に定めることはできないと思います。
    • good
    • 0
この回答へのお礼

ご返答ありがとうございます。
皆様方のご意見とても為になりました。

お礼日時:2005/04/18 10:05

> 結局のところ、どなたのご意見が正しいのでしょうか。



元々メソッド(method)というコトバはSmalltalkで用いられたものではなかったかしら。
意味は「オブジェクトに送られたメッセージに対する反応」 であったはず。
だとすればメソッドはオブジェクト(レシーバ)を必要とするわけで(クラス・メソッドは例外)、そうでないものは関数と呼んで差し支えないのでは。

そんなわけで #1 が常識的なとこではないかと。
    • good
    • 0
この回答へのお礼

ご返答ありがとうございます。
皆様方のご意見とても為になりました。

お礼日時:2005/04/18 10:05

> だとすると、C#におけるメソッドはどうなんでしょう。

ただのメンバ関数をメソッドと'称している'に過ぎないように思えますが。

これはその通りだと思います。

C++の「オブジェクト」というのも、オブジェクト指向でいうところの「オブジェクト」と必ずしも等価でないのと同様、C#における「メソッド」もその言語内のローカルな定義に過ぎないのでしょう。
    • good
    • 0

色々な回答があり情報が錯綜していますが。

。。「関数=メソッド」と考えていいと思います。

まずC++の言語仕様には「メソッド」はないと思います(私自身仕様を把握しているわけではないので自信はありません、ないと思います)。

そのためC++(の仕様)において「メソッドと関数の違いは?」という質問への正確な回答はないと思います。

とは言うもののC++に関しても様々な場面で「メソッド」という言葉が使われています。

Visual C++で「メソッド」という言葉が使われている場面もあります。COM(ActiveX)で外部から操作できる関数を「メソッド」と呼びます(同じように外部から参照や操作できる変数は"プロパティ"と呼びます)。これはマイクロソフトなどが使っているC++での「メソッド」という言葉です。

またC++以外の言語を使っていて新しくC++を始めた人などは「メソッド=関数」という意味合いで使っていることもあります。また「クラスのメンバー関数=メソッド」として扱っている人もいます。これらは多くの場合上で述べたマイクロソフトの"メソッド"という言葉とは違う意味で使っています。


つまり「メソッド」という言葉はきちんとした定義がない(?)ためにその言葉を使っている人によって意味合いが違っています。「メソッド」という言葉に出会ったらその時々でその意味を判断する必要があると思います。しかしどの場合にも"メソッド"が"関数"の1種であることには変わりはないので「メソッド=関数」と考えていいと思います。
    • good
    • 0
この回答へのお礼

ご返答ありがとうございます。
私としてはクラスのメンバ関数がメソッドの事で、
メンバ関数と言う言い回しは、C/C++の方言だと考えていたのですが、
改めて調べ直すと、他の方々のご返答のように、
人によってまちまちなので、何が正しいのか確信がもてなくなりました。
多くの方々から、ご返答を頂けましてありがたいのですが、
結局のところ、どなたのご意見が正しいのでしょうか。

お礼日時:2005/04/12 09:40

#5> 「標準出力というオブジェクトに、putsというメッセージを送ると、文字列が出力されるというメソッドが実行される」といった具合に、メンバ関数とは直結しません。



なるほど、「オブジェクトに送られたメッセージに対する反応」がメソッドで、その実現手段の一つがメンバ関数だと(それでいいですか?)。

だとすると、C#におけるメソッドはどうなんでしょう。ただのメンバ関数をメソッドと'称している'に過ぎないように思えますが。
    • good
    • 0

> ? では メソッド と メンバ関数 の違いは?



C/C++では、メソッドは言語仕様にないので一般的な解釈をせざるを得ないと思います。

「標準出力というオブジェクトに、putsというメッセージを送ると、文字列が出力されるというメソッドが実行される」といった具合に、メンバ関数とは直結しません。
もっと極端な例では、「タイマというオブジェクトに、レジスタへの書き込みというメッセージを送ることで、カウントアップ開始というメソッドが(ハード的に)実行される」というのもあるでしょう。

メンバ関数はメソッドを実現する上で便利な機能ではありますが、メンバ関数を使えばメソッドになるわけでもなければ、メソッドはメンバ関数でしか実現できないものではないと思いますが、いかがでしょう?
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qdefine_singleton_methodについて

define_singleton_methodについて

1.9.1p378を使用しています。

メタプログラミングに興味があって、
Classに動的に生成したmethodを追加する方法を調べてみると
色々な教科書にdefine_methodを使う例が書いてあるのを見つけました。

しかし、実際にプログラムしてみると"undefined method"になってしまいます。

Class.methods.grep /define/
してみると、"define_singleton_method"というものがあり、
define_methodの代わりに使ってみたら一応期待通りに動作しました。

googleで調べてみてもdefine_singleton_methodについて解説が見つけられませんでした。

1.9系になって名前が変わったのでしょうか?
それとも似て非なるものなのでしょうか?

詳しい方、教えてください。<(_ _)>

Aベストアンサー

define_singleton_methodは1.9で追加されたもので、Objectクラスのメソッドです。

一方define_methodはModuleクラスのprivateメソッドなので、ModuleかClassの中から呼ばないといけません。
(ClassクラスはModuleクラスのサブクラス。Rubyのprivateはサブクラスからも見える)

define_methodであとからメソッドを追加しようとする場合、直接外からは呼べないので、間接的にdefine_methodを呼ぶメソッドを作成しておくか、一度Classを開くなどをやらないといけませんが、

define_singleton_methodを使えば、そんなことはせずに、簡単にできるということです。

Q【C++クラス設計】ある関数の引数に、他のクラスのメンバ関数を呼び出す方法【教えて下さい】

C++でクラス設計のコードを書いています。
隠蔽性を大事にするため、(特に必要がない他は)最初からメンバ変数は全てprotected(private)のメンバとして宣言し、getter/setter関数で操作しています。

クラスABCのメンバ関数の引数として、クラスXYZのメンバ関数を呼び出すとき、問題が発生します。
クラスABCのメンバ関数の引数に呼び出した、クラスXYZのget関数によって正しい値が渡されず、引数に意味のない数字が渡されてしまいます。

一方同じ設計で、クラスXYZのメンバ変数をpublicで宣言し(getter関数を使わず変数本体だけ)直接渡すと、意図した決められた値が渡されます。
よって関数の引数に他のクラスの関数を呼び出すときに限りエラーが起きていると思われます。

コードは以下の通りです。
<ABC.h>
class ABC{
public:
void A(int);
};

<ABC.cpp>
#include"ABC.h"
void ABC::A(int i){ printf("%d", i); }

<XYZ.h>
class XYZ{
protected:
static int X;
public:
static int getX(){return X;}
};

<XYZ.cpp>
#include"XYZ.h"
int XYZ::X;

<MAIN.cpp>
#include"ABC.h"
#include"XYZ.h"
int main(void){
ABC abc;
XYZ xyz;
abc.A(xyz.getX); //この行のgetX関数で正しい値が渡されてない(public変数はok)
return 0;
}

クラス設計の隠蔽性を大事に(メンバ変数をprotectedに)したまま、クラスABCのメンバ関数の引数に、クラスXYZのメンバ関数によって正しい値が渡される方法を教えてください。

C++でクラス設計のコードを書いています。
隠蔽性を大事にするため、(特に必要がない他は)最初からメンバ変数は全てprotected(private)のメンバとして宣言し、getter/setter関数で操作しています。

クラスABCのメンバ関数の引数として、クラスXYZのメンバ関数を呼び出すとき、問題が発生します。
クラスABCのメンバ関数の引数に呼び出した、クラスXYZのget関数によって正しい値が渡されず、引数に意味のない数字が渡されてしまいます。

一方同じ設計で、クラスXYZのメンバ変数をpublicで宣言し(getter...続きを読む

Aベストアンサー

誤: xyz.getX
正: xyz.getX()

または

C++/CLI の property 構文を使う

QPostMethodによるアップロード

PostMethodによるアップロードのプログラムを作成しようとしていますが、
HttpClient、PostMethodの使い方がよくわかりません。
いろいろなサイトを見て、

HttpClient client = new HttpClient();
PostMethod post = new PostMethod(url);
・・・
client.executeMethod(post);

とすればよさそうだというところまではわかったのですが、
そもそも、PostMethod(url)の"url"には何を指定すればよいのか、
また、executeMethod(post)を実行すると、何が起こってどのように
アップロードが行われるのかというところの理解ができていません。
基本的なこととは思いますが、どなたかお教えいただけないでしょうか。

Aベストアンサー

ファイルアップロード処理をするには、Webサーバ側に
ファイルアップロードを受け付けるサーバーアプリが必要です。

Javaでクライアント側のアップロードアプリを作る前に、
まずサーバー側のアップロード受け付けアプリを作る必要があります。

WebサーバにPHPをインストールしているなら、
http://www.php-labo.net/tutorial/php/upload.html
に書かれているようなPHPプログラムで、ブラウザからファイルを
アップロードするサーバー側アプリを簡単に作ることができます。

そこまでできたら、ブラウザの代わりにJavaでファイルを
アップロードするクライアントアプリを作ることも可能です。

PostMethod()のurlには、前述のサーバのアップロード受け付けアプリが
ある場所を指定します。
あとはブラウザのファイルアップロード処理がやっているのと同じことを
Javaのクライアントアプリで実装すればよいです。
具体的にはリクエストヘッダーの設定/送信、ファイルデータの読み込み、
マルチパート形式での送信、レスポンスデータの受け取り等が必要です。
このあたりはPostMethod()が自動的にやってくれるわけではありません、
自分で実装する必要があります。

具体的なJavaコーディングは
http://blog.oklab.org/?p=132
あたりが参考になると思います。

ファイルアップロード処理をするには、Webサーバ側に
ファイルアップロードを受け付けるサーバーアプリが必要です。

Javaでクライアント側のアップロードアプリを作る前に、
まずサーバー側のアップロード受け付けアプリを作る必要があります。

WebサーバにPHPをインストールしているなら、
http://www.php-labo.net/tutorial/php/upload.html
に書かれているようなPHPプログラムで、ブラウザからファイルを
アップロードするサーバー側アプリを簡単に作ることができます。

そこまでできたら、ブラウザの代わり...続きを読む

Qクラス型配列を同じクラス内関数の引数に使えますか?

今ゲームを作成中です。クラス型の配列を引数で渡して
その関数内でメンバの値を変えたいと思っています。
下記のような記述を試してみたのですがエラーは出ませんが
配列が関数内で参照できず思うようにいきません。
同じクラス内でクラス型の配列は使えないのでしょうか?
その場合どのようにすれば配列でクラス内メンバの値を
保持すればよいでしょうか?ご回答お願いします。

#define Block_Max (100)

Block* B
Block* BB[]

void main(){
  for(int no=0; no < Block_Max; no++){
    B->Block_Test(no,BB);
  }
}

Block::Block_Test(int no,Block* BB[]){
  BB[no]->B_Test_F = true;
}

Aベストアンサー

このところ VisualStudio は使っていないので的を外しているかもしれませんが....

void Block::BlockTime(int no,Block* BB[],DWORD g_B_Time) にしろ void Block::Block_Add_End(int no,Block* BB[]) にしろ, 配列 BB はこれらの関数の仮引数になっています. つまり, これらの関数内で「BB」と書けば, それは
Block* BB[BLOCK_ADD_MAX];
と定義した BB ではなく仮引数としての BB です.

ということで, 「BBの中の要素数が表示されていた」という「別のクラス内」で「BB」が仮引数として使われているか確認してください. そちらで仮引数になっていないのであれば, 「仮引数になっているかどうか」が影響するのかもしれません.

あと, 「プログラム上 (プログラムなりに) ちゃんと参照できている」んだけど「デバッガでは参照できていない」という可能性もありますね. この質問をするということは「関数内でメンバの値を変えたいと思ってプログラムを書いているにもかかわらずメンバの値が変わっていない」ということだと思うのですが, デバッガ以外でも「メンバの値がおかしい」ことは確認できていますか?

このところ VisualStudio は使っていないので的を外しているかもしれませんが....

void Block::BlockTime(int no,Block* BB[],DWORD g_B_Time) にしろ void Block::Block_Add_End(int no,Block* BB[]) にしろ, 配列 BB はこれらの関数の仮引数になっています. つまり, これらの関数内で「BB」と書けば, それは
Block* BB[BLOCK_ADD_MAX];
と定義した BB ではなく仮引数としての BB です.

ということで, 「BBの中の要素数が表示されていた」という「別のクラス内」で「BB」が仮引数として使われているか確認して...続きを読む

Q)method for cash budgeting

I need to have a consistent method for cash budgeting this year.
今年度の現金予算を作成する一貫性のある方法が必要だ。
上記の文章(原文ママ)ですが、

1)method for cash budgeting
より

2)method of cash budgeting
の方が用例が多いように思います。
意味が違いますか?

また、
3)method of cash budget
ではダメなのでしょうか?

3点教えて頂けませんかm(_ _)m

Aベストアンサー

cash budgetingで現金予算管理

1)method for cash budgeting
現金予算管理のための、(一貫性のある)方法

2)method of cash budgeting
現金予算管理の方法

となるのではないでしょうか。

>3)method of cash budget
ではダメなのでしょうか?

ニュアンスの違いだけと思いますのでどちらでもいいかと思うのですが

[今年度の現金予算管理のためには、一貫性のある(現金管理のための)方法が必要だ]
という事だと思います。

Qクラス内のクラスから1つ目のクラスのメソッドよ呼び出しがうまくいきません^^;

こんにちは、ちょっと分かりにくい質問なんですが。

class c1
{
  int k1();

  class c2
  {
    int k2();
  };
};

と言うのがあったとします。
そこで、k2の関数の内部でk1を呼び出したいのですが、

int k2()
{
  return c1::k1();
}

見たいな事をすると、「静的でない関数の呼び出しが正しくありません」とエラーが出てしまい、コンパイルできません・・・

だからといってk1をc1の外に出してしまうとc1の変数にアクセスできなくなってしまうため、それはできません。

何かいい方法はないでしょうか・・・解決策をお待ちしていますm(_ _)m

Aベストアンサー

クラスの設計がちょっと駄目です。
c2からc1::k1にアクセスしたいなら、
c2がc1のポインタを持つか、k1をstaticメンバにします。
ちなみにstaticメンバはCの関数と同じただの関数でメンバ変数にアクセスできません。
またこの場合c2を内包する意味がありません。
class c1
{
  int k1();
  int k2();
};
でいいのです。

return c1::k1();
これが何故だめか、ですが
c1は実体がありません。その為staticメンバ(静的な関数)である必要があるのです。

class c1
{
  static int k1();
  class c2
  {
    int k2();
  };
};
int c1::k1()
{
return 0;
}
int c1::c2::k2()
{
  return c1::k1();
}

一応これでコンパイルは通りますが。

Q$_SERVER['REQUEST_METHOD']と"POST"が等しいかどうか大文字小文字を区別

せずに判別する方法を教えてください

if($_SERVER['REQUEST_METHOD']==="post")
if($_SERVER['REQUEST_SESSIONMETHOD']=="post")
if(strcasecmp($_SERVER['REQUEST_METHOD'],"post")==0)
if(strcmp($_SERVER['REQUEST_METHOD'],"post")==0)

のいずれがよいでしょうか?

Aベストアンサー

>大文字小文字を区別

区別したいなら
$_SERVER['REQUEST_METHOD']==="post"
でいいんじゃない?

ただ等号での文字列比較に対しては否定的な現場も多いので
strcmp($_SERVER['REQUEST_METHOD'],"post")===0
の方がよいかも

ちなみに多くのサーバーでは「POST」を返すので小文字「post」とはマッチしません。

むしろ
strtolower($_SERVER['REQUEST_METHOD'])==="post"
など小文字同士の比較をしていることを明示した方がよいかと。

Qテンプレートクラス内のテンプレートクラス(インナークラス)のメソッドを実装ファイルで定義したい

現在、ヘッダファイル内で下記のようなクラスを宣言・定義しています。

// test.h
template < typename T1 >
struct A
{
  template < typename T2 >
struct B
  {
    B( A const& arg ) { ... }
  };
};

テンプレートクラスが入れ子になっていて、Bのコンストラクタが引数としてAを取っています。
しかし現状ではコンパイルがとんでもなく遅くなってしまうので、
Bのコンストラクタは宣言のみとし、別途実装ファイル(test.cpp)に定義を書きたいと思っています。

ところがメソッドのシグネチャをどう書けばよいのか分からなくなってしまいました。

苦し紛れに

// test.cpp
template < typename T1, typename T2 >
A<T1>::B<T2>::B( A<T1> const& arg ) { ... }

などと書いてみましたが、違うようです。
解決方法はありますでしょうか?

環境はVC7.1かVC8でコンパイルできればよいです。
よろしくお願いいたします。

現在、ヘッダファイル内で下記のようなクラスを宣言・定義しています。

// test.h
template < typename T1 >
struct A
{
  template < typename T2 >
struct B
  {
    B( A const& arg ) { ... }
  };
};

テンプレートクラスが入れ子になっていて、Bのコンストラクタが引数としてAを取っています。
しかし現状ではコンパイルがとんでもなく遅くなってしまうので、
Bのコンストラクタは宣言のみとし、別途実装ファイル(test.cpp)に定義を書きたいと思っています。

ところが...続きを読む

Aベストアンサー

template < typename T1 >
struct A {
 template < typename T2 >
 struct B {
  B( A const& arg );
 };
};

template<typename T1>
template<typename T2>
A<T1>::B<T2>::B( A<T1> const& arg ) { }

int main() {
 A<int> a;
 A<int>::B<char> c(a);
}

Qmethod#invoke のラッパ

下記のようなリフレクション(動的なメソッド呼び出し)の汎用的なラッパ関数を作成しています。

class Wrapper
{
public static void main(String[] args)
{
Hoge hoge = new Hoge();
// (1)
Wrapper.call(hoge, "testMethod", new Human());
// (2) これはNoSuchMethodException例外発生
Wrapper.call(hoge, "testMethod", new Japanese());
// (3) これもNoSuchMethodException
Wrapper.call(hoge, "testMethod", (Human) new Japanese());

}

public static Object call(Object obj, String method_name, Object ...args)
{
try {
// 引数のクラス配列を取得
Class[] class_ary = new Class[args.length];
for (int i=0; i<args.length; i++)
class_ary[i] = args[i].getClass();


Class c = obj.getClass();
// メソッドインスタンスを取得
Method method = c.getMethod(method_name, class_ary);
// 実行
return method.invoke(obj, args);
}catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

class Hoge {
public void testMethod(Human h) {
System.out.println(h.getClass());
}
}
class Human {

}
class Japanese extends Human {

}

一見うまくうごくようにみえたのですが
(2)のようにすると例外が発生することが最近わかりました。
親クラスにキャストした(3)でも同様です。

理由は

// 引数のクラス配列を取得
Class[] class_ary = new Class[args.length];
 for (int i=0; i<args.length; i++)
  class_ary[i] = args[i].getClass();

のgetClass()の部分がキャストしようがしまいが Japaneseのクラスインスタンスを返すからだというのはわかっているのですが、他の方法が思いつきません。

多態性を備えたラッパ関数を作成することは無理でしょうか?
何か解決策があればアドバイスをお願いします。

下記のようなリフレクション(動的なメソッド呼び出し)の汎用的なラッパ関数を作成しています。

class Wrapper
{
public static void main(String[] args)
{
Hoge hoge = new Hoge();
// (1)
Wrapper.call(hoge, "testMethod", new Human());
// (2) これはNoSuchMethodException例外発生
Wrapper.call(hoge, "testMethod", new Japanese());
// (3) これもNoSuchMethodException
Wrapper.call(hoge, "testMethod", (Human) new Japanese());

}

public static Object call(Object obj, String...続きを読む

Aベストアンサー

こんな感じでしょうか。あんまり詳しくチェックしてませんけれど。

public static Object call(Object obj, String method_name, Object... args) {
try {
// メソッドインスタンスを取得
Method method = findCompatibleMethod(obj.getClass(), args);
// 実行
return method.invoke(obj, args);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

// argsを引数に呼び出せるメソッドをclazzから探します
static Method findCompatibleMethod(Class clazz, Object[] args) throws NoSuchMethodException {
for (Method method : clazz.getMethods()) {
if (isCompatible(method, args)) {
return method;
}
}
throw new NoSuchMethodException();
}

static boolean isCompatible(Method method, Object[] args) {
Class[] clazzes = method.getParameterTypes();
for (int i = 0; i < args.length; i++) {
if (!clazzes[i].isInstance(args[i])) {
return false;
}
}
return true;
}

こんな感じでしょうか。あんまり詳しくチェックしてませんけれど。

public static Object call(Object obj, String method_name, Object... args) {
try {
// メソッドインスタンスを取得
Method method = findCompatibleMethod(obj.getClass(), args);
// 実行
return method.invoke(obj, args);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

// argsを引数に呼び出せるメソッドをclazzから探します
static Method findCompatibleMethod(Class clazz, Object[] args) throws...続きを読む

QC言語において、関数とその役割、また、引数とその役割、仮引数、実引数とは?

C言語初心者です。
そもそもPC使うのも苦手ですがよろしくお願いします。
C言語において、関数とその役割、また、引数とその役割、仮引数、実引数の役割を、実例を用いて簡潔に説明していただけると助かります。お願いします。

Aベストアンサー

そんなに一気に理解しようとしても難しいですね。
http://www.kyoto-su.ac.jp/~yamada/ap/parameter_argument.html
を眺めてみてください(仮引数と実引数の意味が書いてある。ただしC言語であんまり仮引数がとか実引数が、という言い方はしないような)。
C言語においては全ての処理のかたまりが「関数」です。関数は何かの処理を行って値を返すことも返さないこともあります。
ここの例でいうとf(int x)は値を返す関数、main()は返さない関数で、ここからプログラムの処理が始まります(そういうルールになっている)。
このページのプログラムはちょっと古い書き方なんで今だと警告が出る可能性があります。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報