jak polaczyc polimorfizm z kontenerami

Odpowiedz Nowy wątek
kosakos
2006-09-13 20:50
kosakos
0

Witajcie.

Aby jasno sformulować problem, pozwole sobie na krotki wstep.
Oczywiste jest, ze jesli stworze jakas klase (podstawowa) i zdefiniuje w niej pewna wirtualna funkcje skladowa, to tworzac klase pochodna od danej klasy podstawowej moge w niej zdefiniowac funkcje o tej samej nazwie i liscie parametrow formalnych, lecz innym ciele. Wowczas, jesli napisze funkcje zewnetrzna, przyjmująca jako parametr formalny wskaznik (badz referencje) do obiektu klasy podstawowej, w ciele ktorej siedzi wywołanie funkcji wirtualnej na rzecz danego wskaznika (badz referncji), to taka funkcja zewnetrzna moze przyjac rowniez wskaznik (badz referencje) do obiektu klasy pochodnej i wywolac funkcje wirtualna juz na rzecz tegoz. To sie nazywa polimorfizm.

A teraz moj problem.
Otoz mam klase podstawowa Obiekt1 i pochodna od niej klase Obiekt2. W tych klasach definiuje funkcje wirtualna. W programie głównym definiuje typy listowe w postaci:

typedef list <Obiekt1 *> ListaObiektow1;
typedef list <Obiekt2 *> ListaObiektow2;
ListaObiektow1  lista1;
ListaObiektow2  lista2;

Moje pytanie brzmi: czy mozna stworzyc funkcje zewnetrzna, ktora formalnie przyjmowac bedzie w jakis sposob parametr typu ListaObiektow1, ale bedzie mozna do niej równiez przeslać parametr typu ListaObiektow2? W skrocie moge zapytac: czy jezeli istnieje dziedziczenie klas, to czy moze istniec pewne dziedziczenie tak zdefiniowanych typow list?

Chcialbym bowiem moc korzystac z polimorfizmu zwiazanego z powyzszymi klasami, ale majac jednoczesnie zgrupowane w listach wskazniki do obiektow klas.

Mam nadzieje, że powyzszy wywod jest zrozumialy

Teraz przykladowy kod (pisze go na sucho, by przedstawic problem wiec moze nie dzialac):

//---------------- 
//   DEFINICJE KLAS

class Obiekt1
{
   public:
          virtual void funkcja () { cout << "jestem z klasy Obiekt1" <<endl;}
};
class Obiekt2: public Obiekt1
{
   public:
          void funkcja () { cout << "jestem z klasy Obiekt2" <<endl;}
};
//----------------
//   DEFINICJE I DEKLARACJE FUNKCJI GLOBALNYCH
typedef list <Obiekt1 *> ListaObiektow1;
typedef list <Obiekt2 *> ListaObiektow2;

ListaObiektow1  lista1;
ListaObiektow2  lista2;

    void SpecFun (Obiekt1 *)
    void SpecFunList (ListaObiektow1) // - potrzebuje wlasnie takiej analogicznej funkcji
                       //   dla list

//----------------
//   PROGRAM GLOWNY
int main()
{
    Obiekt1 *ob1;
    Obiekt2 *ob2;

// dynamiczne stworzenie 3 wskazników do obiektow obu klas i zapisanie ich do 
// odpowiednich list 

   for(int i=0; i<3; i++)
  {
     ob1 = new Obiekt1;
     lista1.push_back(ob1);
     ob2 = new Obiekt2;
     lista2.push_back(ob2);
  }

// wywolanie funkcji wirtualnych na rzecz poszczegolnych skladnikow list

    ListaObiektow1::iterator i1;
    ListaObiektow2::iterator i2;

// za pomoca specjalnej funkcji Spec_Fun(Obiekt1 *) robimy to dla pojedynczego skladnika 
// (w tym wypadku pierwszego) listy

    i1 = lista1.begin();
    ob1 = (*i1);
    Spec_Fun(ob1);

    i2 = lista2.begin();
    ob2 = (*i2);
    Spec_Fun(ob2);

// za pomoca petli po wszystkich skladnikach listy

    while(i1 != lista1.end())
    {
        ob1 = (*i1);
    ob1->funkcja();
    i1++;
    }

    while(i2 != lista2.end())
    {
        ob2 = (*i2);
    ob2->funkcja();
    i2++;
    }

// a wiec jesli chce wywolac funkcje wirtualna funkcja() dla wszystkich 
// skladnikow list to musze to zrobic w petlach, a wolalbym na przyklad
// tak:

   SpecFunList(lista1);
   SpecFunList(lista2);

// zwalnianie pamieci
   i1 = lista1.begin();
   while (i1 != lista1.end()) 
   {
       delete (*i1);
          ++i1;
   }
   i2 = lista2.begin();
   while (i2 != lista2.end()) 
   {
       delete (*i2);
          ++i2;
   }

  return 0;
}

//----------------
//DEFINICJE FUNKCJI GLOBALNYCH

    void SpecFun (Obiekt1 * obiekt)
    {
    obiekt->funkcja();
    }

    void SpecFunList (ListaObiektow1 lista) // to pewnie powinno byc inaczej ale w takim sensie
    {
      ListaObiektow1::iterator i;
      Obiekt1 * ob;

      i = lista.begin();
      while(i != lista.end())
      {
          ob = (*i);
      ob->funkcja();
      i++;
      }
    }

Jesli ktos wytrwal do konca tego zawilego tlumaczenia to bardzo dziekuje i prosze o pomoc wwyjasnieniu kwestii.

Pozdrawiam

Pozostało 580 znaków

2006-09-13 21:09

Rejestracja: 13 lat temu

Ostatnio: 6 lat temu

0

Może funkcja szablonowa ? :-/


Pozostało 580 znaków

kosakos
2006-09-13 21:52
kosakos
0

A moge poprosic o jakis przyklad realizacji. Dzieki.

Pozostało 580 znaków

2006-09-13 21:59

Rejestracja: 13 lat temu

Ostatnio: 6 lat temu

0

Poczytaj o funkcjach szablonowych (Templates) i sam zmontujesz.
Wkońcu obiekty listy których używasz to też szablony .


Pozostało 580 znaków

2006-09-13 22:18

Rejestracja: 14 lat temu

Ostatnio: 2 miesiące temu

0

Sorki, za poprzedni poast, ale nie doczytałem że Obiekt2 dziedziczy po Obiekt1. Wystarczy że użyjesz typedef list <Obiekt1 *> ListaObiektow1; dla obu obiektów. Skoro funkcja w Obiekt1 jest wirtualna to automatycznie funkcja w Obiekt2 też jest, więc po co dwa typedefy ?


Pozdrawia DzieX

int getRandomNumber() { return 4; }

Pozostało 580 znaków

2006-09-13 22:29

Rejestracja: 13 lat temu

Ostatnio: 6 lat temu

0

Zrób wspólną klasę czysto wirtualną dla Obiekt1 i Obiekt2 i po zabiegu. :-)


Pozostało 580 znaków

2006-09-13 22:42

Rejestracja: 14 lat temu

Ostatnio: 2 miesiące temu

0
dzejo napisał(a)

Zrób wspólną klasę czysto wirtualną dla Obiekt1 i Obiekt2 i po zabiegu. :-)

Ale po co skoro jedna dziedziczy po drugiej...


Pozdrawia DzieX

int getRandomNumber() { return 4; }

Pozostało 580 znaków

2006-09-14 06:35

Rejestracja: 13 lat temu

Ostatnio: 6 lat temu

0

Masz rację :-)


Pozostało 580 znaków

kosakos
2006-09-14 10:16
kosakos
0

DzieX:

czy chodzi Tobie o taki zapis

typedef list <Obiekt1 *> ListaObiektow1, ListaObiektow2;
ListaObiektow1 lista1;
ListaObiektow2 lista2;

czy moze tak

typedef list <Obiekt1 *> ListaObiektow1;
ListaObiektow1 lista1, lista2;

Pozostało 580 znaków

2006-09-14 11:59

Rejestracja: 14 lat temu

Ostatnio: 2 miesiące temu

0

Przecież to to samo ;P Ale drugi lepszy, bo mniej typedefów :)


Pozdrawia DzieX

int getRandomNumber() { return 4; }

Pozostało 580 znaków

kosakos
2006-09-14 12:17
kosakos
0

No tak :-/ Poczatkujacy jestem ... ;-)

Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0