Strukturierung von Klassen
-
Ja ne, Du hast Recht. Das sollte ich noch ändern. Hatte ich gar nicht mehr richtig auf dem Schirm.
Wichtig war mir die Trennung von Art des Objekt, die Verwaltung, und die Berechnungen. Zwar habe ich immer noch eine Klasse, die äußerlich alles beinhaltet, aber sie beherbergt nur die Daten und führt sie zur Berechnung weiter.
Wen ich Operation und Ausgabe an einem Objekt haben möchte, kann ich mir das nicht anders vorstellen?
-
@lemon03 sagte in Strukturierung von Klassen:
Wen ich Operation und Ausgabe an einem Objekt haben möchte, kann ich mir das nicht anders vorstellen?
Ostream ist doch auch eine Klasse, die alles ausgeben kann, ohne mit dem, was sie ausgibt, etwas zu tun zu haben.
-
@lemon03 sagte in Strukturierung von Klassen:
Wen ich Operation und Ausgabe an einem Objekt haben möchte, kann ich mir das nicht anders vorstellen?
Spricht aus meiner Sicht nix dagegen. Ich habe auch öfter Klassen, die Daten halten und verändern und zusätzlich noch eine oder mehrere Ausgabemöglichkeiten haben:
- saveToFile( ... )
- toString()
- ostream-Operator
Je nachdem was man braucht.
-
@seppj sagte in Strukturierung von Klassen:
@lemon03 sagte in Strukturierung von Klassen:
Wen ich Operation und Ausgabe an einem Objekt haben möchte, kann ich mir das nicht anders vorstellen?
Ostream ist doch auch eine Klasse, die alles ausgeben kann, ohne mit dem, was sie ausgibt, etwas zu tun zu haben.
Und GraphObject ist doch eine Klasse, die mit dem was die ausgibt, nichts zu tun hat? Sie hat nur einen vector<Point>, den sie weiterreicht und ausgibt.
-
Und wohin ausgibt? Direkt mittels
cout
?Und was mir noch aufgefallen ist:
- bei deinen (erstgezeigten) Klassen fehlen die
public:
-Bereiche. Oder sollen diese nur über diefriend
-Klassen ansprechbar sein (also lesend und schreibend)? - du hast doch die Klasse
SideLength
(wenn mich auch der Name irritiert)? Warum hast du in deinen Klassen (besondersPPAttributes
) dann noch einzelne_x, _y, _z
-Member? - den Aufbau (bzw. die Schnittstelle) deiner beiden Klassen
PointProjection
undAffineTransformation
finde ich auch eigenartig (keinen Konstruktor, Rückgabewert der Funktionen - auf jeweiligen Memberpoints
???).
- bei deinen (erstgezeigten) Klassen fehlen die
-
Zwar in die Konsole, aber rein über eine WinAPI-Funktion. Die ist aber ganz unten, das sie im restlichen Code nicht mehr auftaucht. Die beiden Ausgaben schauen so aus
void GraphObject::draw( const DrawArea& draw, const int x, const int y, const Char& chr, const int char_mix_mode, const bool show ) const { if ( wired ) { if ( edges.size() > 0 ) { for ( std::size_t i = 0; i < edges.size(); ++i ) { const std::size_t a = edges[ i ].a; const std::size_t b = edges[ i ].b; drawLine( draw, points[ a ].cx +x, points[ a ].cy +y, points[ b ].cx +x, points[ b ].cy +y, chr, char_mix_mode ); } } else { drawDot( draw, points.front().cx +x, points.front().cy +y, chr, char_mix_mode, show ); } } else { std::cerr << "GraphObject::draw(): wired warning\n"; std::cerr << "no WireFrame"; ready(); } }
void GraphObject::plot( const DrawArea& draw, const int x, const int y, const int char_mix_mode ) const { for ( const auto& point : points ) { drawDot( draw, point.cx +x, point.cy +y, point.chr, char_mix_mode ); } }
-
Ja, die Attribute-Klassen ( vielleicht hätte ich eher private-structs nehmen sollen) sollen vollkommen private sein und nur für die Friend-Klasssen nutzbar.
-
Habe ich das? Das muss dann ein Fehler sein. Die Seitenlängen sind wie die Namen nur zur besseren Übersicht beim printen eines Objekt. Die kommen in den Berechnungen nicht vor. Zwar sind die bei WireFrame alle gleich, aber bei Shape sind es zwei verschiedene. Da die Objekte dreidimensional dargestellt werden, habe ich auch drei benannt.
Jedenfalls haben die mit den Attribute-Klassen rein gar nichts zu tun. -
Ja, das war mit besten Wissen und Gewissen. Ich habe da lange überlegt, wie ich das hinbekomme. Irgendwann hat sich dies als die beste Lösung rauskristallisiert.
Ich hatte bestimmt auch eine Konstruktor-Übergabe überlegt, das es die nicht gibt, war wahrscheinlich das es damit nicht wie gewünscht lief.
-
-
Ich meinte eher die
print()
-Funktionen in den einzelnen Klassen, oder was machen diese?Ok, dann ist
SideLength
nur zufällig genauso eine Datenstruktur, um drei Dimensionen zu speichern.
Und beiPPAttributes
meinte ich daher so etwas:struct Vector // or whatever name you like { double x, y, z; }; struct PPAttributes { Vector move; // ... Vector scale; };
Und wie benutzt du dann die beiden Klassen
PointProjection
undAffineTransformation
? Greifst du (z.B. beim Initialisieren oder beim Auslesen) direkt aufpoints
zu?Das ist alles andere als gutes OOP.
-
Die print-Funktionen "printen" die Daten als reine Zahlenwerte
void GraphObject::print( const int amount ) const { console.setCursorHome(); std::cout << name << " side lengths:\n"; auto n = 8; const auto np = 3; std::cout << "\n x: " << std::setw( n ) << std::fixed << std::setprecision( np ) << side_length.x; std::cout << " y: " << std::setw( n ) << std::fixed << std::setprecision( np ) << side_length.y; std::cout << " z: " << std::setw( n ) << std::fixed << std::setprecision( np ) << side_length.z; pp.print(); af.print(); int l = 0; std::cout << "\nPoints:"; for ( const auto& point : points ) { std::cout << "\n x: " << std::setw( n ) << std::fixed << std::setprecision( np ) << point.x; std::cout << " y: " << std::setw( n ) << std::fixed << std::setprecision( np ) << point.y; std::cout << " z: " << std::setw( n ) << std::fixed << std::setprecision( np ) << point.z; ++l; if ( l > amount ) break; } l = 0; n = 4; std::cout << "\n\nMap:"; for ( const auto& point : points ) { std::cout << "\n cx: " << std::setw( n ) << point.cx; std::cout << " cy: " << std::setw( n ) << point.cy; ++l; if ( l> amount ) break; } pressKey(); }
Was Du meinst, muss ich erst mal kurz überlegen, auf die Schnelle kann ich jetzt dazu nichts schreiben.
Tja, und der letzte Punkt? Muss ich wahrscheinlich dann noch mal ransetzen.
-
Genau das meinte ich. Was wenn du dann die Daten in eine Datei schreiben wolltest?
Dafür gibt es doch den Stream-Operator:std::ostream& operator <<(std::ostream& os, const GraphObject &graphObject);
Übergebe einfach
std::ostream&
als Parameter an deineprint
-Funktionen und rufe dann diese im Stream-Operator auf.
Natürlich passen dannconsole.setCursorHome()
undpressKey()
nicht mehr, aber diese gehören ja auch generell nicht in eine Logik-Klasse.
-
Aha, danke. Nachvollziehbar. Das schaue ich mir mal an.