• ベストアンサー

Cで多様性を表現するには

こんにちは、あっちこっちとウェブを検索しましたが これと言った答えが見つからないので書かせていただ きます。 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();  } }

質問者が選んだベストアンサー

  • ベストアンサー
  • ency
  • ベストアンサー率39% (93/238)
回答No.5

No2、No4 ency です。 No4 の以下の箇所訂正します。 > しかも、ダウンキャストすると~ 誤) ダウンキャスト 正) スーパークラスにキャスト う~ん、何を勘違いしたんだろうか。。。 ダウンキャストはスーパークラスからサブクラスへのキャスト (下向きだから「ダウン」キャスト) のことで、Java だと「ナローイング変換」だったかな? ちなみに、さらに補足しますと、Java のインタフェースは多重に継承させることが可能ですが、この実装ではそれはできません。 # 今回のポリモルフィズムの話とは、直接関係ありませんが。。。 あと、クラスごとにメソッドをテーブル管理すると、メソッドの追加も簡単になりますね。 # 他にもいろいろ案は浮かんできますが、混乱の元になりそうですので、 # このへんでやめておきます。 …と、まあ、そこまでやる必要は果たしてあるのかどうかわかりませんが、C でポリモルフィズムを実現する方法は、考えればいろいろありそうですね。 以上、これまでの回答に対する補足でした。

umepapa05
質問者

お礼

詳細な説明をありがとうございます。 まず今のところは、ここで止めておこうと思います。 まずは、いただいたサンプルを元にリンクリストやらなんやら追加して自分なりの理解を広げようと思います 関数ポインタは使い方が広くて、設計の意図を良く理解してないと混乱しそうですね。オープンソースを読んで読みなれ出来るようにがんばります

その他の回答 (4)

  • ency
  • ベストアンサー率39% (93/238)
回答No.4

No2 ency です。 > Cでデザインパターン(構造パターン?)みたいなものがあるもんでしょうか? どうなんでしょうか。。。 たぶんないと思いますけど。。。(?) 「継承」って、スーパークラスのフィールドやらメソッドをサブクラスも持っていることですから、実装レベルでは、サブクラスがスーパークラスのデータ構造を含んでいることになりますよね。 しかも、ダウンキャストするとスーパークラスのメソッドなりフィールドにアクセスできなければなりませんから、スーパークラスのデータ構造はサブクラスの先頭に含んでいることになります。 ということから考えて、No2 ができあがったわけです。 # インタフェースの実装でも、根本は継承といっしょですよね。 あとは、new 相当のものが malloc() だとか、Java には GC があるけど C にはないから C++ で言うところの delete 相当のものが必要だとか…そんな感じでした。

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.3

>「cat->mif.run = cat_run;」の部分とか、ほんとにこれでいいのか? 関数のポインタに関数を入れるのは、問題ないと思います。 >Cat* cat = (Cat*)malloc(sizeof(Cat*)); sizeof(Cat*)は、だめでしょう!

umepapa05
質問者

お礼

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

  • ency
  • ベストアンサー率39% (93/238)
回答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; }

umepapa05
質問者

お礼

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

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答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)(); } }

umepapa05
質問者

お礼

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

  • Java初心者です

    次のようなプログラムを作りました interface Vehicle{ void drive(); } abstract class Animal{ abstract void show(); } class Lion extends Animal{ public void show(){ System.out.println("ライオンです"); } } class Horse extends Animal implements Vehicle{ public void show(){ System.out.println("馬です"); } public void drive(){ System.out.println("乗り物として使えます"); } } class Elephant extends Animal implements Vehicle{ public void show(){ System.out.println("象です"); } public void drive(){ System.out.println("乗り物として使えます"); } } class Bear extends Animal{ public void show(){ System.out.println("熊です"); } } class twentyeight{ public static void main(String args[]){ Animal an[]; an = new Animal[4]; an[0] = new Lion(); an[1] = new Horse(); an[2] = new Elephant(); an[3] = new Bear(); for(int i = 0;i < an.length;i++){ if(an[i] instanceof Vehicle){ an[i].drive();//ここにエラーが出る } else{ an[i].show(); } } } } インターフェイスを実装しているオブジェクトを判別し、そのdriveメソッドの呼び出しをしたいのですができません、どなたか教えてください。

    • ベストアンサー
    • Java
  • 抽象クラス、インターフェイスについて

    少し長いですが、以下にコードを書きました。これでコンパイルすると、13個ほどエラーが出て、何がなんだかわかりません。何が間違っているのでしょうか?よろしくお願いします。ちなみに本を見ながらの独学です。 //のりものインターフェイス interface iVehicle { abstract void show(); } //車くらす class Car implements iVehicle { private int num; private double gas; public Car(int n, double g)) { num = n; gas = g; System.out.println("ナンバー" + num +"ガソリン量" + gas +"の車を作成しました"); } public void show() { System.out.println("車のナンバーは" + num +"です"); System.out.println("ガソリン量は" + gas +"です"); } } //飛行機クラス class Plane extends Vehicle { private int flight; public Plane(int f) { flight = f; System.out.println("便" + flight +"の飛行機を作成しました"); } public void show() { System.out.println("飛行機の便は" + flight +"です"); } } class sample8 { public static void main(String args[]) { iVehicle ivc[]; ivc = new iVehicle[2]; ivc[0] = new Car(1234, 20.5); ivc[1] = new Plane(232); for(int i=0; i<ivc.length; i++){ if(vc[i] instanceof Car) ivc[i].show(); } } }

    • ベストアンサー
    • Java
  • "add"とは?f

    class Car { int num; double gas; void setNum(int n) { num = n; System.out.println("ナンバーを" + num + "にしました。"); } void setGas(double g) { gas = g; System.out.println("ガソリン量を" + gas + "にしました。"); System.out.println("この車は満タンで40リットル入ります。"); } void show() { System.out.println("車のナンバーは"+num+"です。"); System.out.println("ガソリン量は"+gas+"です。"); } } class Prog11_1 { public static void main(String args[]) { Car car1 = new Car(); Car car2 = new Car(); car1.setNum(1234); car1.setGas(20.5); car2.setNum(5678); car2.setGas(30.8); car1.addGas(10.0); car2.addGas(10.0); car1.show(); car2.show(); } } 上記のプログラムの足りないところを補い、完成させるというものなんですが、"add"というのは一体どのような役割を持っているものなんでしょうか? 分かる方いらっしゃいましたら、よろしくお願いします。

    • ベストアンサー
    • Java
  • NoSuchMethodErrorが解決できません。

    実行時エラーNoSuchMethodErrorが出て困っています。 どこを修正すればいいのでしょうか? class A implements Runnable{ int x; int y; public void run(){ for(int i = 0;i < 100;i++){ x++; y++; System.out.println("x="+x+"y="+y); } } } class B{ public static void main(String args[]){ new Thread(new A()).start(); new Thread(new A()).start(); } }

    • ベストアンサー
    • Java
  • データ型で質問です。

    JAVA勉強中のものです。 データ型で質問があります。 class Animal{ public void run(int speed){ System.ou.println("My animal is running"); } } class Dog extends Animal{ public void run(long speed){ System.out.println("My dog is running"); } } class Test{ Public Static void main(String args[]){ Animal myAnimal = new Dog();   -----* myAnimal.run(5); } } 出力結果は My animal is running になりますが、わかりません。 *行は実際のオブジェクトはDog型で,次のmyAnimal.run(5)は インスタンスメソッドなので、オブジェクトのDogを見に行くと 思うのですが、違うのですか? 本に書いてあったので解説お願いします。

    • ベストアンサー
    • Java
  • Java言語のインタフェースについて

    Java言語を学習している者です。 インターフェースについて理解できずに困っております。 ここでは、Runnableインターフェースを例にとります。 (1)正しいコード public class ThreadTest implements Runnable { public static void main (String args[]) { ThreadTest ins = new ThreadTest(); Thread th = new Thread(ins); th.start(); for(int i = 0; i < 10; i++) { System.out.println("main : " + i); } } public void run() { for(int i = 0; i < 10; i++) { System.out.println("run : " + i); } } } (1)のコードは正常に動きます。 (2)間違ったコード (implements Runnableを記述しなかった場合) public class ThreadTest{ public static void main (String args[]) { ThreadTest ins = new ThreadTest(); Thread th = new Thread(ins); th.start(); for(int i = 0; i < 10; i++) { System.out.println("main : " + i); } } public void run() { for(int i = 0; i < 10; i++) { System.out.println("run : " + i); } } } (2)のコードでは、 Thread th = new Thread(ins); で、 コンストラクタ―Thread(ThreadTest)は未定義です。 とエラーが出てしまいます。 確かに未定義なのですが、(1)でも定義していないように思えます。 Runnableインターフェースの働きのお陰だと言うことはわかるのですが、どういった働きによるものなのかがわかりません。 インターフェースのについて、 ・インターフェースのフィールドは必ず定数。 ・インターフェースのメソッドは必ず抽象メソッド。 ・インターフェースはインスタンスを作ることが出来ない。 ・抽象メソッドは必ず実装しなければならない。 は理解しているつもりです。 今回の質問をするに当たって、 RunnableのAPI http://java.sun.com/javase/ja/6/docs/ja/api/java/lang/Runnable.html を見たのですが、それでも理由が分からないので質問致します。 もし宜しかったら、APIの見方についてもコメントして頂けるとありがたいです。 宜しくお願いします。

    • ベストアンサー
    • Java
  • インターフェイス(独習JAVAのP234課題1について)

    インターフェイスの参照のコーディングについて質問です interface Locomotion{ void stop(); } interface Sound{ void beep(); } abstract class Robot{ } class RobotA extends Robot{ } class RobotA1 extends RobotA implements Sound{ public void beep(){ System.out.println("RobotA1: beep"); } } class RobotB extends Robot implements Locomotion{ public void stop(){ System.out.println("RobotB: stop"); } } class RobotC extends Robot implements Locomotion,Sound{ public void stop(){ System.out.println("RobotC: stop"); } public void beep(){ System.out.println("RobotC: beep"); } } class RobotType{ private final static int NUM = 4; public static void main(String args[]){ Robot robots[] = new Robots[NUM];     Robot robots[0] = new RobotA(); Robot robots[1] = new RobotA1(); Robot robots[2] = new RobotB(); Robot robots[3] = new RobotC(); //Soundインターフェイスを実装しているメソッドの呼び出し for(int i=0;i<NUM;i++){ if(robots[i] instanceof Sound){ Sound sound = (Sound)robots[i]; sound.beep(); } } for(int i=0;i<NUM;i++){ if(robots[i] instanceof Locomotion){ Locomotion locomotion = (Locomotion)robots[i]; locomotion.stop(); } } } } main処理でSoundインターフェイス等を参照する時に、 なぜ、Sound sound = (Sound)robots[i];の用に記述しないと駄目なのでしょうか? robots[i].beep();で参照できると思ったのですが、コンパイルエラーになってしまいます アドバイスよろしくお願い致します

  • クラスのフィールドの値を配列に代入する方法

    フィールドの値を代入したいのですが、 java.lang.ArrayIndexOutOfBoundsException というエラーが出てしまい、どうすればいいのかわかりません。 どのように対処すればいいのでしょうか? class Car { String carname; int height; int width; int length; } class public static void main(String[] args) throw IOException { Car car[]; car = new Car[5]; System.out.println("車の情報を入力してください。"); BufferedReader br1 = new BufferedReader(new InputStreamReader(System.in); for(int i=0; i<5; i++){ car[i] = new Car(); System.out.println(i+1 + "台目の車の名前を入力してください。"); String str1 = br1.readLine(); System.out.println("車の高さを入力してください。"); String str2 = br1.readLine(); System.out.println("車の幅を入力してください。"); String str3 = br1.readLine(); System.out.println("車の長さを入力してください。"); String str4 = br1.readLine(); int h1 = Integer.parseInt(str2); int w1 = Integer.parseInt(str3); int l1 = Integer.parseInt(str4); car[i].carname = str1; car[i].height = h1; car[i].weith =w1; car[i].length =l1; } for(int i=0; i<5; i++){ int c_h[] = new int[5]; c_h[i] = car[i].height; } } よろしくお願いします。

    • ベストアンサー
    • Java
  • JavaでのポリモーフィズムをC#で表現するには?

    最近ふと気になったのですが、以下のJavaのコードと等価なコードは、C#ではどのように書けばよいのでしょうか? --- public Class1 {   public void foo() {     System.out.println("Class1");   } } public Class2 extends Class1 {   public void foo() {     System.out.println("Class2");     super.foo();   } } public Class3 extends Class2 {   public void foo() {     System.out.println("Class3");     super.foo();   } } --- 気分的には次のように書きたいところなのですが、このように書くとコンパイルエラーになってしまいます。 --- public class Class1 {   public virtual void foo() {     Console.WriteLine("Class1");   } } public class Class2 : Class1 {   public virtual override void foo() {     Console.WriteLine("Class2");     base.foo();   } } public class Class3 : Class2 {   public override void foo() {     Console.WriteLine("Class3");     base.foo();   } } --- 調べた限り、ストレートな方法で記述することは不可能だと感じたのですが、やはりそうなのでしょうか? そうだとしたら、現実にこのように記述する必要が生じた場合には、どのように対処すればよいのでしょうか? また、C#の言語仕様はなぜこのようになっているのでしょうか?(VMの仕組みも関係あるのでしょうか?) 知っていらっしゃる方がいましたら、教えていただけると助かります。

  • インターフェイスを2つ以上実装

    こんにちは。 高橋麻奈さん著の「やさしいJava」を使ってJavaを学んでいるのですが、インターフェイスのところでつまずいています。 インターフェイスは2つ以上クラスに実装できるということですが、本に書いてあるサンプル文では2つ実装されているものが載っています。 それにさらにもう一つインターフェイスを自分で書き加えて実装させてみたのですが、エラーが出てコンパイルできませんでした。書き加える前の状態では普通にコンパイル&実行できました。 ということは書き加えた部分が間違ってるはずなのですが自分には何処が間違っているのかわかりません。 以下にそのコード全文を載せておきますね。(色インターフェイス関連が書き加えた部分) どなたかわかるかたがいらっしゃいましたらご回答お願いします。 //のりものインターフェイス interface iVehicle { void vShow(); } //材料インターフェイス interface iMaterial { void mShow(); } //色インターフェイス interface iColor(); { void cShow(); } //車クラス class Car implements iVehicle, iMaterial, iColor { private int num; private double gas; public Car(int n, double g) { num = n; gas = g; System.out.println("ナンバー" + num + "ガソリン量" + gas + "の車を作成しました"); } public void vShow() { System.out.println("車のナンバーは" + num + "です"); System.out.println("ガソリン量は" + gas + "です"); } public void mShow() { System.out.println("車の材質は鉄です"); } public void cShow() { System.out.println("車の色は黄色です"); } } class Sample4 { public static void main(String args[]) { Car car1 = new Car(1234, 20.5); car1.vShow(); car1.mShow(); car1.cShow(); } }

    • ベストアンサー
    • Java

専門家に質問してみよう