Dostęp do zmiennych funkcji dziedziczonej wirtualnie

0

Witam. Stworzylem sobie mniej wiecej takiego rodzaju dziedziczenie za pomoca dziedzieczneia wirtualnego:

      -- Kwadrat --- Prostokat
   /                \

Punkt --- Okrag --- Elipsa

-- Trojkat

Wszystko jest dobrze, do momentu wywolywania zmiennych obiektu Elipsa oraz Prostokat, ktore pochodza z klasy bazowej - Punkt. Zmienne te bez wzgledu na wartosci wpisane, przy odczycie za kazdym razem maja wartosci zerowe. Wiem, ze problem zaczyna sie wraz z dziedziczeniem wirtualnym, ale zeby zaimplementowac klase Elipsa, musze dziedziczyc wirtualnie Kwadrat oraz Okrag, zeby nie bylo niejednoznacznosci metod z klasy bazowej, czyli Punkt.

Pytanie brzmi jak prawidlowo zaimplementowac konstruktory, aby poprawnie przyjmowaly wartosci zmiennych x, y dla tworzonych obiektow klas Elipsa oraz Prostokat.
No i moj pelny kod programu pisany w DEV-C++:

#include <iostream>

using namespace std;

class Punkt
{
      public:
             Punkt(){}
             Punkt(int w_x, int w_y):x(w_x),y(w_y){cout << "konstruktor punktu" << endl;}
             virtual void rysuj()
             {       cout << "Rysuje punkt, wspolrzedne: " << endl;
                     cout << "x = " << x << ", y = " << y << endl;
             }
             virtual ~Punkt(){}
      protected:
                int x,y;
};


class Okrag : public virtual Punkt
{
      public:
             Okrag(int w_promien):Punkt(),promien(w_promien){};
             Okrag(int w_x, int w_y, int w_promien):Punkt(w_x,w_y),promien(w_promien){cout << "konstruktor okregu" << endl;}
             virtual ~Okrag(){}
             virtual void rysuj()
             {       cout << "Rysuje Okrag, wspolrzedne: " << endl;
                     cout << "x = " << x << ", y = " << y << endl; 
                     cout << "promien = " << promien << endl;
             }
      protected:
                int promien;
};

class Trojkat : public Punkt
{
      public:
             Trojkat(int w_x, int w_y, int w_kat, int w_dl_przy_prost, int w_dl_przeciw_prost):
                         Punkt(w_x,w_y),kat(w_kat),dl_przy_prost(w_dl_przy_prost),
                         dl_przeciw_prost(w_dl_przeciw_prost){cout << "konstruktor trojkata" << endl;}
             virtual ~Trojkat(){}
             virtual void rysuj()
             {       cout << "Rysuje Trojkat, wspolrzedne: " << endl;
                     cout << "x = " << x << ", y = " << y << endl; 
                     cout << "Kat = " << kat << endl;
                     cout << "Przyprostokatna = " << dl_przy_prost << endl;
                     cout << "Przeciwprostokatna = " << dl_przeciw_prost << endl;
             }
      private:
                int kat,dl_przy_prost,dl_przeciw_prost;
};

class Kwadrat : public virtual Punkt
{
      public:
             Kwadrat(int w_x, int w_y, int dl_bok):Punkt(w_x,w_y),bok(dl_bok){cout << "konstruktor kwadratu" << endl;}
             virtual ~Kwadrat(){}
             virtual void rysuj()
             {       cout << "Rysuje kwadrat, wspolrzedne: " << endl;
                     cout << "x = " << x << ", y = " << y << endl; 
                     cout << "dlugosc boku = " << bok << endl;
             }
      protected:
                int bok;     
};

                     
class Prostokat : public Kwadrat
{
      public:
             Prostokat(int w_x, int w_y, int dl_bok, int w_drugi_bok):
                           Kwadrat(w_x,w_y,dl_bok),drugi_bok(w_drugi_bok)
                           {  cout << "konstruktor prostokatu" << endl;}
             virtual ~Prostokat(){}
             virtual void rysuj()
             {       cout << "Rysuje prostokat, wspolrzedne: " << endl;
                     cout << "x = " << x << ", y = " << y << endl; 
                     cout << "Pierszy bok = " << bok << endl;
                     cout << "Drugi bok = " << drugi_bok << endl;
             }
      private:
                int drugi_bok;
};

class Elipsa : public Kwadrat, public Okrag
{
      public:
             Elipsa(int w_x, int w_y, int dl_bok, int w_promien):
                           Kwadrat(w_x,w_y,dl_bok),Okrag(w_promien)
                           {  cout << "konstruktor elipsy" << endl;}
             virtual ~Elipsa(){}
             virtual void rysuj()
             {       cout << "Rysuje elipse, wspolrzedne: " << endl;
                     cout << "x = " << x << ", y = " << y << endl; 
                     cout << "Promien = " << promien << endl;
                     cout << "Bok = " << bok << endl;
             }
};

main()
{
  const int ilosc_elementow = 6;

  Punkt * tab[ilosc_elementow];
  Punkt * sp;
  
  sp = new Punkt(4,2);
  tab[0]=sp;
  sp = new Kwadrat(7,1,9);
  tab[1]=sp;
  sp = new Okrag(5,4,3);
  tab[2]=sp;
  sp = new Trojkat(3,4,45,10,15);
  tab[3]=sp;
  sp = new Prostokat(1,2,5,7);
  tab[4]=sp;
  sp = new Elipsa(7,2,10,8);
  tab[5]=sp;
    
    for (int i=0;i<ilosc_elementow;i++)
    {    tab[i]->rysuj();
         cout << endl;
    }
    
    delete sp;
    
    for(int i=0;i<ilosc_elementow;i++)
            delete tab[i];        

  system("PAUSE");
}
0

Na początek kilka uwag co do kodu.

  • main powinno mieć typ zwracany (int)
  • nie wywołuj delete sp, bo na ostatniej komórce tablicy się wywali - kasujesz coś co już jest skasowane. W ogóle to sp to nie jest potrzebne.

Teraz właściwa część. Przy dziedziczeniu z od klas wcześniej dziedziczących wirtualnie musisz wywołać jawnie konstruktor ich klasy bazowej. Czyli tak:

Prostokat(int w_x, int w_y, int dl_bok, int w_drugi_bok):
		Kwadrat(w_x,w_y,dl_bok), Punkt(w_x, w_y), drugi_bok(w_drugi_bok)

oraz

Elipsa(int w_x, int w_y, int dl_bok, int w_promien):
		Kwadrat(w_x,w_y,dl_bok), Punkt(w_x, w_y), Okrag(w_promien)

Pomijam fakt, że twoja hierarchia klas jest troche bez sensu i "na siłe".

0

Dzieki Dziex:-) To co tyczy sie hierarchi, to z powodow czysto akademickich i masz racje, sp nie jest potrzebne, zrobilem tak:

  tab[0]=new Punkt(4,2);
  tab[1]=new Kwadrat(7,1,9);
  tab[2]=new Okrag(5,4,3);
  tab[3]=new Trojkat(3,4,45,10,15);
  tab[4]=new Prostokat(1,2,5,7);
  tab[5]=new Elipsa(7,2,10,8);

[browar]

0

Z powodów czysto akademickich powinieneś zastosować kompozycję, a nie dziedziczenie po punkcie (w szczególności wirtualne). Już nie mówiąc o takich szczegółach, jak to, że elipsa nie jest okręgiem na przykład (tylko na odwrót).

Punkt -  tyle

         -- Elipsa ---- Okrąg
       /
Figura ---- Kwadrat ---- Prostokąt
       \
         -- Trójkąt
Figura nie zawiera żadnych punktów. 
Elipsa zawiera 2 (bo ma 2 ogniska).
Okrąg zawiera dwa, ale z definicji się one pokrywają.
Trójkąt ma 3.
Kwadrat i prostokąt ma 4 (chociaż do ich zdefiniowania wystarczają de facto 2).
0

@Ranides

E tam, czasami trzeba bo tak każą... Z niektórymi ćwiczeniowcami na uczelniach jest tak, że nie możesz pokazać, że wiesz więcej niż on, ani że śmiesz go poprawiać :/

0

Po czesci sie z tym zgadzam Ranides - dziedziczeniem Elipsy po kwadracie i okregu. Jednak w moim przypadku kazda figura ma wspolrzedne x,y na plaszczyznie (dlatego jest potrzebna klasa punkt) i ma dane potrzebne do okreslenia rozmiarow tych figur. Sadze, ze doszedlem do sedna sprawy, bo chodzilo tak naprawde o dostep do skladnikow klasy bazowej.
Dzieki :-)

0

Ja mam podobnie, tylko że:

template<class T> class SimpleList {
public:
  class Iterator {
  protected:
    SimpleList<T> *list;
  }
  class Manipulator : public Iterator {
  public:
    virtual void InsertNode(const T& x) {
      list->N() += 1; //tu błąd
    }
  }
 }

ale tam gdzie jest list->N() dostaję błąd:
error: ‘list’ was not declared in this scope
Wie ktoś może o co chodzi? Próbowałem : Iterator, : SimpleList::Iterator i : SimpleList<T>::Iterator, ale wygląda na to, że kompilator wie o który Iterator chodzi tylko coś z tym dziedziczeniem nie tak. Jedyne co mi przyszło do głowy, to że te virtual przed void InsertNode ma coś do tego, ale jak usunąłem, to nic nie pomogło. Nie mam więcej pomysłów

0
this->list->N()

powiedzieć trzeba kompilatorowi, do kogo ten list należy, bo siedzisz w szablonie, i tutaj podpowiadać często trzeba intencje swoje.

0

Dzięki wielkie, dokładnie o to chodziło :) (Ale i tak chyba porzucę ten kod nad którym siedzę, nie mam pojęcia jakim cudem coś takiego mogło się kiedykolwiek kompilować, kod do obiektowego raytracingu dorzucony do książki z 1994r :/ Po drodze napotkałem błędy o jakich mi się nie śniło plus buga w gcc )

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