この人頭いいなと思ったエピソード

こんにちは、あっちこっちとウェブを検索しましたが
これと言った答えが見つからないので書かせていただ
きます。

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();
 }
}

A 回答 (5件)

No2、No4 ency です。



No4 の以下の箇所訂正します。

> しかも、ダウンキャストすると~

誤) ダウンキャスト
正) スーパークラスにキャスト

う~ん、何を勘違いしたんだろうか。。。
ダウンキャストはスーパークラスからサブクラスへのキャスト (下向きだから「ダウン」キャスト) のことで、Java だと「ナローイング変換」だったかな?

ちなみに、さらに補足しますと、Java のインタフェースは多重に継承させることが可能ですが、この実装ではそれはできません。
# 今回のポリモルフィズムの話とは、直接関係ありませんが。。。

あと、クラスごとにメソッドをテーブル管理すると、メソッドの追加も簡単になりますね。
# 他にもいろいろ案は浮かんできますが、混乱の元になりそうですので、
# このへんでやめておきます。

…と、まあ、そこまでやる必要は果たしてあるのかどうかわかりませんが、C でポリモルフィズムを実現する方法は、考えればいろいろありそうですね。

以上、これまでの回答に対する補足でした。
    • good
    • 0
この回答へのお礼

詳細な説明をありがとうございます。
まず今のところは、ここで止めておこうと思います。
まずは、いただいたサンプルを元にリンクリストやらなんやら追加して自分なりの理解を広げようと思います

関数ポインタは使い方が広くて、設計の意図を良く理解してないと混乱しそうですね。オープンソースを読んで読みなれ出来るようにがんばります

お礼日時:2006/03/09 19:34

No2 ency です。



> Cでデザインパターン(構造パターン?)みたいなものがあるもんでしょうか?

どうなんでしょうか。。。
たぶんないと思いますけど。。。(?)

「継承」って、スーパークラスのフィールドやらメソッドをサブクラスも持っていることですから、実装レベルでは、サブクラスがスーパークラスのデータ構造を含んでいることになりますよね。

しかも、ダウンキャストするとスーパークラスのメソッドなりフィールドにアクセスできなければなりませんから、スーパークラスのデータ構造はサブクラスの先頭に含んでいることになります。

ということから考えて、No2 ができあがったわけです。
# インタフェースの実装でも、根本は継承といっしょですよね。

あとは、new 相当のものが malloc() だとか、Java には GC があるけど C にはないから C++ で言うところの delete 相当のものが必要だとか…そんな感じでした。
    • good
    • 0

>「cat->mif.run = cat_run;」の部分とか、ほんとにこれでいいのか?


関数のポインタに関数を入れるのは、問題ないと思います。
>Cat* cat = (Cat*)malloc(sizeof(Cat*));
sizeof(Cat*)は、だめでしょう!
    • good
    • 0
この回答へのお礼

おはようございます。
>sizeof(Cat*)は、だめでしょう!
はい、だめだめでした。sizeof(Cat)でした。
No.2さんが書かれてるように明示的に書いた方がよりよいですね

お礼日時:2006/03/09 10:08

こんな感じのもありかなぁ。

。。
# わざわざ 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;
}
    • good
    • 0
この回答へのお礼

ありがとうございます。No.1さんのを自分なりに
いじってる間にほぼ同じような解答をいただきまして
大変参考になりました。
自分のソース・・・汚いですね^^;
freeもしてないし・・・
丁寧に書いていただきまして本当にありがとうございます。この機会に色々なアイデアを聞きたいので、こういうのもあるよっと言うのがありましたらお願いします。

Cでデザインパターン(構造パターン?)みたいなものがあるもんでしょうか?

お礼日時:2006/03/09 03:26

手抜きだけども、こんな感じ?



#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)();
}
}
    • good
    • 0
この回答へのお礼

夜中にありがとうございます。
参考にしていただきまして、早速自分なりに書いて
みました。追記でアドバイス・気になる点がありましたら、お手数ですがお願いします。
特に「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;
}

お礼日時:2006/03/09 03:19

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