こんにちは、あっちこっちとウェブを検索しましたが
これと言った答えが見つからないので書かせていただ
きます。
C言語で多様性を表現するにはどのようにすればいいで
しょうか?関数ポインタを使用すると出来そうだと言
うとこまでは理解したのですが・・・
以下にJavaで書いたものをCでどうやって表現したら
良いかご教授ください。また、参考になるポインタな
どもあれば宜しくお願いします。
public interface MoverIF{
public void run();
}
public class Car implements MoverIF{
public Car(){}
public void run(){
System.out.println("Car run");
}
}
public class Dog implements MoverIF{
public Dog(){}
public void run(){
System.out.println("Dog run");
}
public static void main(String arg){
MoverIF mi[] = new MoverIF[2];
mi[0] = new Dog();
mi[1] = new Car();
for(int i=0;i<2;i++){
mi[i].run();
}
}
No.5ベストアンサー
- 回答日時:
No2、No4 ency です。
No4 の以下の箇所訂正します。
> しかも、ダウンキャストすると~
誤) ダウンキャスト
正) スーパークラスにキャスト
う~ん、何を勘違いしたんだろうか。。。
ダウンキャストはスーパークラスからサブクラスへのキャスト (下向きだから「ダウン」キャスト) のことで、Java だと「ナローイング変換」だったかな?
ちなみに、さらに補足しますと、Java のインタフェースは多重に継承させることが可能ですが、この実装ではそれはできません。
# 今回のポリモルフィズムの話とは、直接関係ありませんが。。。
あと、クラスごとにメソッドをテーブル管理すると、メソッドの追加も簡単になりますね。
# 他にもいろいろ案は浮かんできますが、混乱の元になりそうですので、
# このへんでやめておきます。
…と、まあ、そこまでやる必要は果たしてあるのかどうかわかりませんが、C でポリモルフィズムを実現する方法は、考えればいろいろありそうですね。
以上、これまでの回答に対する補足でした。
詳細な説明をありがとうございます。
まず今のところは、ここで止めておこうと思います。
まずは、いただいたサンプルを元にリンクリストやらなんやら追加して自分なりの理解を広げようと思います
関数ポインタは使い方が広くて、設計の意図を良く理解してないと混乱しそうですね。オープンソースを読んで読みなれ出来るようにがんばります
No.4
- 回答日時:
No2 ency です。
> Cでデザインパターン(構造パターン?)みたいなものがあるもんでしょうか?
どうなんでしょうか。。。
たぶんないと思いますけど。。。(?)
「継承」って、スーパークラスのフィールドやらメソッドをサブクラスも持っていることですから、実装レベルでは、サブクラスがスーパークラスのデータ構造を含んでいることになりますよね。
しかも、ダウンキャストするとスーパークラスのメソッドなりフィールドにアクセスできなければなりませんから、スーパークラスのデータ構造はサブクラスの先頭に含んでいることになります。
ということから考えて、No2 ができあがったわけです。
# インタフェースの実装でも、根本は継承といっしょですよね。
あとは、new 相当のものが malloc() だとか、Java には GC があるけど C にはないから C++ で言うところの delete 相当のものが必要だとか…そんな感じでした。
No.3
- 回答日時:
>「cat->mif.run = cat_run;」の部分とか、ほんとにこれでいいのか?
関数のポインタに関数を入れるのは、問題ないと思います。
>Cat* cat = (Cat*)malloc(sizeof(Cat*));
sizeof(Cat*)は、だめでしょう!
おはようございます。
>sizeof(Cat*)は、だめでしょう!
はい、だめだめでした。sizeof(Cat)でした。
No.2さんが書かれてるように明示的に書いた方がよりよいですね
No.2
- 回答日時:
こんな感じのもありかなぁ。
。。# わざわざ malloc() する必要もなかったかな。。。
========================================================
#include <stdio.h>
#include <stdlib.h>
/*------------------------------------------------
MoverIF インタフェース相当のもの
------------------------------------------------*/
struct MoverIF
{
void (*run)( void );
};
/*------------------------------------------------
Car クラス相当のもの
------------------------------------------------*/
struct Car
{
struct MoverIF mover;
};
void car_run( void )
{
printf( "Car run\n" );
}
struct Car *create_car( void )
{
struct Car *car;
car = malloc( sizeof( struct Car ) );
if ( car != NULL )
{
car->mover.run = car_run;
}
return car;
}
void delete_car( struct Car *car )
{
free( car );
}
/*------------------------------------------------
Dog クラス相当のもの
------------------------------------------------*/
struct Dog
{
struct MoverIF mover;
};
void dog_run( void )
{
printf( "Dog run\n" );
}
struct Dog *create_dog( void )
{
struct Dog *dog;
dog = malloc( sizeof( struct Dog ) );
if ( dog != NULL )
{
dog->mover.run = dog_run;
}
return dog;
}
void delete_dog( struct Dog *dog )
{
free( dog );
}
/*------------------------------------------------
メイン処理
------------------------------------------------*/
int main( void )
{
struct MoverIF *mi[2];
int i;
mi[0] = (struct MoverIF*)create_car();
mi[1] = (struct MoverIF*)create_dog();
if ( mi[0] == NULL || mi[1] == NULL )
{
printf( "Out of memory!" );
exit(1);
}
for ( i = 0; i < 2; i++ )
{
mi[i]->run();
}
delete_car( (struct Car*)mi[0] );
delete_dog( (struct Dog*)mi[1] );
return 0;
}
ありがとうございます。No.1さんのを自分なりに
いじってる間にほぼ同じような解答をいただきまして
大変参考になりました。
自分のソース・・・汚いですね^^;
freeもしてないし・・・
丁寧に書いていただきまして本当にありがとうございます。この機会に色々なアイデアを聞きたいので、こういうのもあるよっと言うのがありましたらお願いします。
Cでデザインパターン(構造パターン?)みたいなものがあるもんでしょうか?
No.1
- 回答日時:
手抜きだけども、こんな感じ?
#include <stdio.h>
#include <stdlib.h>
typedef struct moveIF {
char *className;
void (*run)();
} MoveIF;
void Dog_run(void){
printf("Dog run\n");
}
MoveIF Dog_new(void){
MoveIF a;
a.className="Dog";
a.run=Dog_run;
return(a);
}
void Cat_run(void){
printf("Cat run\n");
}
MoveIF Cat_new(void){
MoveIF a;
a.className="Cat";
a.run=Cat_run;
return(a);
}
void main(void){
MoveIF mi[2];
int i;
mi[0] = Dog_new();
mi[1] = Cat_new();
for(i=0;i<2;i++){
(mi[i].run)();
}
}
夜中にありがとうございます。
参考にしていただきまして、早速自分なりに書いて
みました。追記でアドバイス・気になる点がありましたら、お手数ですがお願いします。
特に「cat->mif.run = cat_run;」の部分とか、ほんとにこれでいいのか?って思ってしまうのですが・・
#include <stdio.h>
#include <stdlib.h>
typedef struct mif{
void (*run)();
}MoveIF;
typedef struct dog{
char* name;
char* color;
char* type;
MoveIF mif;
}Dog;
typedef struct cat{
char* name;
char* color;
MoveIF mif;
}Cat;
void cat_run(){
printf("A cat is running\n");
}
void dog_run(){
printf("A dog is running\n");
}
int main(int argc, char** argv){
MoveIF mi[2];
int i;
Cat* cat = (Cat*)malloc(sizeof(Cat*));
Dog* dog = (Dog*)malloc(sizeof(Dog*));
cat->name = "mike";
cat->color= "white";
cat->mif.run = cat_run;
dog->name = "poti";
dog->color = "white";
dog->type = "Shiba";
dog->mif.run = dog_run;
mi[0] = cat->mif;
mi[1] = dog->mif;
for(i=0;i<2;i++){
(mi[i].run)();
}
return 0;
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
int main()、void main()、void...
-
多重定義が起きている?--lnk20...
-
静的でないメンバ関数の呼び出...
-
gcc: incompatible pointer type
-
既定のコンストラクタがありま...
-
コールバックって・・・
-
C# Controls.Addで動的に配置し...
-
C/C++でのScene管理について
-
C言語 ① 5秒間 1秒間隔で点滅を...
-
C言語 extern について
-
voidポインタをハンドルへ
-
【gcc・cygwin】multiple defin...
-
戻り値を返す関数の前に(void)...
-
C++にてtemplateで受け取った任...
-
ArduinoでMouse関数を使用して...
-
コンパイルエラー: LNK2001
-
マルチメディアタイマー
-
関数の戻り値にその関数のポイ...
-
動的に作ったリッチエディット...
-
アルディーノ初心者です。 下記...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
【gcc・cygwin】multiple defin...
-
C++にてtemplateで受け取った任...
-
戻り値を返す関数の前に(void)...
-
静的でないメンバ関数の呼び出...
-
多重定義が起きている?--lnk20...
-
既定のコンストラクタがありま...
-
C# Controls.Addで動的に配置し...
-
int main()、void main()、void...
-
void*型の配列について
-
(void)0 はどんな意味ですか
-
gcc: incompatible pointer type
-
C# KeyDownイベントでショート...
-
C言語 ① 5秒間 1秒間隔で点滅を...
-
Notepad++の関数リスト表示の変...
-
コールバックって・・・
-
マルチメディアタイマーの使用方法
-
_beginthreadにて発生するコン...
-
C#でラジオボタンを設定に記録...
-
VC++でGetKeyboardStateがうま...
-
typedef unsigned int UINT;が...
おすすめ情報