objektorientiertes c



  • hi,

    ich versuche gerade objektorientiertes c zu verwenden...
    ich habe ein dynamisches array (in dem fall std::vector, um den code kurz zu halten!) welches alle typen von tieren speichern soll...
    in c++ wurde ich nun eine basisklasse animal schreiben und dog, cat davon ableiten...

    ist es moeglich cat, dog direkt in das dynamische array zu speichern? im moment ist der typ immer animal...

    #include <iostream>
    #include <vector>
    using namespace std;
    
    struct animal_vtable {
        const char* (*sound)();
    };
    
    struct animal {
        struct animal_vtable methods;
        const char* name;
    };
    
    const char* cat_sound() {
        return "meow!";
    }
    
    const char* dog_sound() {
        return "bark!";
    }
    
    struct animal_manager {
        vector<animal*> vec;
    };
    
    void add_animal(struct animal_manager *m, struct animal *a) {
        m->vec.push_back(a);
    }
    
    void print_animals(struct animal_manager *m) {
    	for (int i = 0; i < m->vec.size(); i++) {
    		cout << m->vec[i]->methods.sound() << endl;
    	}	
    }
    
    // wie kann man das hier eleganter machen, und static vermeiden?
    struct animal *new_cat(const char *name) {
    	static animal cat = {{&cat_sound}, name};
    	return &cat;
    }
    
    // wie kann man das hier eleganter machen, und static vermeiden?
    struct animal *new_dog(const char *name) {
    	static animal dog = {{&dog_sound}, name};
    	return &dog;
    }
    
    int main() {
        animal_manager m;
        add_animal(&m, new_cat("cat"));
        add_animal(&m, new_dog("dog"));
    	print_animals(&m);
    
        return 0;
    }
    

  • Mod

    Könntest du mal in C++ beschreiben, was du vor hast?



  • ca. so:

    #include <iostream> 
    #include <vector> 
    #include <string>
    using namespace std; 
    
    enum type {
    	cat_animal,
    	dog_animal
    };
    
    class animal {
    private: 
        string name; 
    	type animal_type;
    
    public:
    	animal(string name_, type animal_type_): name(name_), 
    	                                         animal_type(animal_type_) {}
    	virtual string make_sound() = 0;
    }; 
    
    class cat : public animal {
    private:
    	int some_variabe2;
    
    public:
    	cat(string name_): animal(name_, cat_animal) {} 
    
    	virtual string make_sound() {
    		return "meow!";
    	}
    };
    
    class dog : public animal {
    private:
    	int some_variabe1;
    
    public:
    	dog(string name_): animal(name_, dog_animal) {} 
    
    	virtual string make_sound() {
    		return "bark!";
    	}
    };
    
    class animal_manager { 
    private:
        vector<animal*> vec; 
    
    public:
        void add_animal(animal *a) { 
    		vec.push_back(a); 
        }
    
        void print_animals() { 
    		for (int i = 0; i < vec.size(); i++) { 
            	cout << vec[i]->make_sound() << endl; 
        	}
        }
    }; 
    
    int main() { 
        animal_manager m; 
        m.add_animal(new cat("susi")); // i know we need to delete this object from the heap...
        m.add_animal(new dog("struppi")); // i know we need to delete this object from the heap...
        m.print_animals(); 
    
        return 0; 
    }
    


  • ich versuche gerade folgendes buch zu lesen und den c++ code auf c zu mappen: http://www.cs.rit.edu/~ats/books/ooc.pdf



  • Vererbung geht so, falls das die Frage war:

    struct dog
    {
    	animal base;
    	int some_variabe1;
    };
    

    Die Entsprechung von new ist in C nicht static , sondern malloc .



  • und wie kann ich dog in einem dynamischen array e.g.

    vector<animal*> vec;
    

    (achtung c++ code) speichern?



  • Ein Zeiger ist keine Referenz; wenn du das berücksichtigst, läuft doch alles wie gewünscht:

    #include <stdio.h>
    
    struct animal_vtable {
      const char* (*sound)();
    };
    
    struct animal {
      struct animal_vtable methods;
      const char* name;
    };
    
    const char* cat_sound()
    {
      return "meow!";
    }
    
    const char* dog_sound()
    {
      return "bark!";
    }
    
    struct animal_manager {
      struct animal vec[100];
      int i;
    };
    
    void add_animal(struct animal_manager *m, struct animal a)
    {
      m->vec[m->i++] = a;
    }
    
    void print_animals(struct animal_manager *m)
    {
      for (int i = 0; i < m->i; i++) {
        puts( m->vec[i].methods.sound() );
      }
    }
    
    // wie kann man das hier eleganter machen, und static vermeiden?
    struct animal new_cat(const char *name)
    {
      struct animal cat = { { &cat_sound }, name };
      return cat;
    }
    
    // wie kann man das hier eleganter machen, und static vermeiden?
    struct animal new_dog(const char *name)
    {
      struct animal dog = { { &dog_sound }, name };
      return dog;
    }
    
    int main()
    {
      struct animal_manager m = { 0 };
      add_animal(&m, new_cat("cat"));
      add_animal(&m, new_dog("dog"));
      print_animals(&m);
    
      return 0;
    }
    


  • dog *d = malloc(sizeof(*d));
    //.. vtable und andere Member initialisieren ..
    
    //beides ist möglich, wenn base am Anfang der Struktur steht:
    animal *a = &d->base;
    animal *b = (animal *)d;
    
    //darf man auch:
    dog *e = (dog *)a;
    




  • man kann sowas machen um inheritance zu simulieren. wie kann ich mir einen konstruktor / destructor bauen?

    #include <stdio.h>
    
    typedef struct {
      int x;
      int y;
    } point;
    
    typedef struct {
      point center;
      int radius;
    } circle;
    
    void init_point(point *p, int x, int y)
    {
      p->x = x;
      p->y = y;
    }
    
    void init_circle(circle *c, int x, int y, int r)
    {
      init_point((void *)c, x, y);
      c->radius = r;
    }
    
    int main(void) {
    	// your code goes here
    
    	circle c;
    
    	init_circle(&c, 1, 2, 3);
    
    	return 0;
    }
    


  • kann jemand mit ein besseres beispiel zeigen?

    #include <stdio.h>
    
    typedef struct {
      int x;
      int y;
    } point;
    
    typedef struct {
      point center;
      int radius;
    } circle;
    
    void init_point(point *p, int x, int y)
    {
      p->x = x;
      p->y = y;
    }
    
    void init_circle(circle *c, int x, int y, int r)
    {
      init_point((void *)c, x, y);
      c->radius = r;
    }
    
    point NewPoint() 
    {
      point p;
      p.x = 0;
      p.y = 0;
      return p;
    }
    
    void FreePoint(point *this_)
    {
    }
    
    circle NewCircle() 
    {
      circle ret;
      ret.center = NewPoint();
      ret.radius = 0;
      return ret;
    };
    
    void FreeCircle(circle *this_)
    {
    }
    
    int main(void) {
    	// your code goes here
    
    	circle c;
    	c = NewCircle();
    
    	init_circle(&c, 1, 2, 3);
    
    	FreeCircle(&c);
    
    	return 0;
    }
    


  • hi, ich habe nun ein basic example erstellt. wie kann ich den konstructor / destructor aus C++ nachbauen?

    #include <stdio.h>
    #include <math.h>
    
    struct shape;
    
    struct shape_vtable {
      float (*calc_area) (struct shape*);
    };
    
    struct shape {
    	int x;
    	int y;
    	struct shape_vtable *vtable;
    };
    
    struct shape NewShape() {
    	struct shape s;
    	s.x = 0;
    	s.y = 0;
    	return s;
    }
    
    void FreeShape(struct shape *this_) {
    }
    
    static void init_shape(struct shape *s, int x, int y) {
    	s->x = x;
    	s->y = y;
    }
    
    static float calc_area(struct shape *s) {
    	return s->vtable->calc_area(s);
    }
    
    struct circle {
    	struct shape super;
    	int radius;
    };
    
    struct circle NewCircle() {
    	struct circle ret;
    	ret.super = NewShape();
    	ret.radius = 0;
    	return ret;
    }
    
    void FreeCircle(struct circle *this_) {
    }
    
    static float circle_calc_area(struct shape *s) {
    	struct circle *c = (struct circle*)s;
    
    	return (c->radius * c->radius) / M_PI;
    }
    
    static struct shape_vtable circle_vtable = {
    	.calc_area = circle_calc_area,
    };
    
    static void init_circle(struct circle *c, int x, int y, int r) {
    	init_shape((void *)c, x, y);
    	c->super.vtable = &circle_vtable;
    	c->radius = r;
    }
    
    int main(void) {
    	// your code goes here
    
    	struct circle c;
    	c = NewCircle();
    
    	init_circle(&c, 1, 2, 3);
    
    	struct shape *s = (struct shape*)&c;
    	printf("%f", calc_area(s));
    
    	FreeCircle(&c);
    
    	return 0;
    }
    

Log in to reply