Witam,
Od razu tytułem wstępu zamieszczam link do aktualnej wersji projektu:
http://www.sendspace.pl/file/b24934630d71df94def42ec
Opis zgrubsza projektu:
Mamy klasę abstrakcyjną Figure, po której dziedziczą: Square (kwadrat), Rectangle (prostokąt), Rhombus (romb) i Quadrilateral (czworokąt). Elementami składowymi Figure są cztery punkty(wierzchołki) (które, od razu mówię, że z niepodważalnych przyczyn nie mogą być w tablicy, jakby kto się krzywił na switche w kodzie), oraz jej nazwa. Poza tym są funkcje czysto wirtualne: Area (pole) oraz Perimeter (obwód), oraz funkcja SayHello która wypisuje nazwę. Ponadto jest jeszcze color, ale wgl z tego pola póki co nie korzystam.
Poza konstruktorami bezparametrowym oraz kopiującym, każda z 4 figur posiada odpowiednio takie konstruktory:
Quadrilateral - inicjalizowany 4ma punktami
Rhombus - inicjalizowany dwoma przeciwległymi punktami i kątem przy nich
Rectangle - inicjalizowany dwoma przeciwległymi punktami i kątem (skierowanym) pomiędzy przekątną p1-p3 a bokiem p1-p2
Square - inicjalizowany dwoma przeciwległymi punktami.
Różnią się one tak, żeby uniknąć sytuacji, że mamy np. kwadrat, którego współrzędne wierzchołków wskazują na to, że wcale nie jest kwadratem, a te warunki wejściowe do konstruktorów są konieczne i wystarczające by powstała dana figura.
Poza tym zdefiniowałem sobie trochę pomocniczych klas-narzędzi geometrycznych (folder GeometryHelp) takie jak: Point, Vector, Segment (odcinek, wektor zaczepiony), Line (prosta), które zawierają pola definiujące je i podstawowe metody dokonujące operacji na nich. Poza tym jest jeszcze GeometricHelper, który zawiera bardziej skomplikowane statyczne metody, których argumentami jest kilka, często różnych klas, obiektów z folderu GeometryHelp.
Poza tym jedna klasa MathHelper, zawierająca jedną metodę sprawdzającą czy dwie liczby double są w przybliżeniu równe.
Poza tym folder FigureHelp - z enumem reprezentującym figury, oraz klasą FigureHelper, która:
-
sprawdza, jaką figurą jest figura dana na wejściu, na podstawie rozmieszczenia wierzchołków (z przybliżeniem do 10 miejsca po przecinku) i zwraca odpowiednią "figurę" z enuma;
-
zmienia figurze jeden wybrany punkt na inny.
-
- nie podoba mi się rozwiązanie że ta metoda jest tu, a nie w figurze, owszem, ale konieczne było sprawdzenie czy wybrany przez usera punkt jest prawidłowy, tj. czy boki po zmianie się nie krzyżują. Do tego celu musiałem stworzyć Quadrilateral, aby móc sprawdzić, czy jest on prawidłowy. A jako że to Quadrilateral dziedziczy po Figure, Figure nie powinien mieć odniesienia na Quadrilateral, więc nie potrafi go stworzyć. A stworzyć instancji Figure, by zbadać czy boki się nie krzyżują nie można, bo jest to przecież klasa abstrakcyjna (i musi taka pozostać, z tych samych, niepodważalnych przyczyn)
Program najpierw tworzy 4 różne figury (dane testowe zhardkodowane w programie zobrazowane są tutaj: http://www.sendspace.pl/file/a30511f43c92a6f36d087b3), wypisuje wszystkie na ekranie. Potem tworzy tablicę na wskaźniki do figur i wrzuca do niej adresy tych 4 figur. Następnie daje userowi do ręki możliwość zmiany wierzchołków.
I tu wreszcie zaczyna się problem. O ile przed zmianą wszystko było ok - tzn. mimo, że wszystko było wskaźnikiem na figurę, to każda figura liczyła pole na swój sposób - wołana była prawidłowa funkcja wirtualna. Ale w momencie, gdy chcę zmienić mój kwadrat na prostokąt przystający do wbudowanego prostokąta -- oczywiście muszę to zrobić w dwóch krokach. Więc przykładowo przesuwam wierzchołek p4 na (-1, -3). Obecnie powinienem mieć czworokąt o polu i obwodzie (co już wyliczyłem) odpowiednio równych: 18 i ok. 28,6834. Jednak, mimo że po przesunięciu wierzchołka figura została poprawnie przez FigureHelper zinterpretowana jako czworokąt, i stworzony został potem czworokąt o prawidłowych wierzchołkach, to pole i obwod dalej jest liczone wg. sposobu kwadratu - wołane są metody Square::Area() oraz Square::Perimeter()!. Nie rozumiem czemu tak się dzieje. Przecież ta figura jest już czworokątem, nie kwadratem.