X Instanzen von einem Objekt speichern
-
Hallo Leute,
ich habe ein kleines Programm geschrieben, welches eine Eingabe (Projektname und Stunden) fordert. Nun erstelle ich immer eine Instanz von der Klasse SProject und packe dort die Werte rein - mithilfe des Konstruktors.
Die ganzen Instanzen speicher in einem Vector
vector<SProject> Projects;. Nun würde mich Interessieren ob der Code so wie ich in geschrieben habe auch vernünftig ist. Und wie sieht es aus mit
delete? Ich habe gelesen das ich ein
deletenur brauche wenn ich eine Instanz mit dem Schlüsselwort
newerstelle.
SProject.h
#ifndef SPROJECT_H #define SPROJECT_H #include <string> class SProject { public: SProject(); SProject(std::string sName, int nHours); virtual ~SProject(); void DisplayProject(); private: std::string m_sName; int m_nHours; }; #endif // SPROJECT_HSProject.cpp
#include <iostream> #include "SProject.h" SProject::SProject(){ //ctor } SProject::SProject(std::string sName, int nHours = 0){ SProject::m_sName = sName; SProject::m_nHours = nHours; } SProject::~SProject(){ //dtor } void SProject::DisplayProject(){ std::cout << std::endl << std::endl << "Name:\t" + SProject::m_sName << std::endl << "Hours:\t" << SProject::m_nHours; }main.cpp
#include <iostream> #include <string> #include <vector> #include "SProject.h" using namespace std; int main(){ string name; int hours; vector<SProject> Projects; for(int i = 0; i < 3; i++){ cout << "Name: "; cin >> name; cout << "Stunden: "; cin >> hours; SProject sproject(name, hours); Projects.push_back(sproject); } return 0; }Wäre eine ProjektManager Klasse sinnvoll? In der Methoden wie z.B. CreateProject oder DeleteProject drin sind?
Gruß
Lukas
-
KreativerName schrieb:
Nun würde mich Interessieren ob der Code so wie ich in geschrieben habe auch vernünftig ist.
Wozu definierst du einen Destruktor und warum auch nocht virtual?
Wozu der leere Konstruktor?
Warum benutzt du im Konstruktor keine Initialisierungsliste?
Warum verwendest du SProject::m_sName statt m_sNameKreativerName schrieb:
Und wie sieht es aus mit
delete? Ich habe gelesen das ich ein
deletenur brauche wenn ich eine Instanz mit dem Schlüsselwort
newerstelle.
Dann weißt du ja schon alles. Was ist die Frage?
KreativerName schrieb:
Wäre eine ProjektManager Klasse sinnvoll? In der Methoden wie z.B. CreateProject oder DeleteProject drin sind?
Nur, wenn die Projekte dort verwaltet werden. Vorsicht: Klassen, die Manager heißen, tendieren dazu, zu viele Aufgaben zu übernehmen.
-
Danke für die Antwort manni66.
manni66 schrieb:
Wozu definierst du einen Destruktor
Das kann ich dir nicht sagen. Ich dachte (denke immer noch), dass eine Klasse einen Destruktor besitzen muss.
manni66 schrieb:
und warum auch nocht virtual?
virtual ist in dem Fall wirklich überflüssig.
manni66 schrieb:
Wozu der leere Konstruktor?
Ist es sinnvoller einen Konstruktor mit vorgegebenen Parameterwerten zu definieren?
z.B.
SProject::SProject(std::string sName = "ProjektName", int nHours = 0){ SProject::m_sName = sName; SProject::m_nHours = nHours; }Und dafür den Standartkonstruktor zu entfernen?
manni66 schrieb:
Warum benutzt du im Konstruktor keine Initialisierungsliste?
Ich habe mir die Initialisierungslisten nochmal angeschaut und habe gelesen, dass sie die Schritte 1. Speicherbeschaffung und 2. die Zuweisung zusammenfasst und somit schneller als ein normaler Konstruktor ist.
Wann benutzt man also Initialisierungslisten und wann normale Konstruktoren? Oder nehme ich immer
Initialisierungslisten?SProject(std::string sName, int nHours) : m_sName(sName), m_nHours(nHours){ }manni66 schrieb:
Warum verwendest du SProject::m_sName statt m_sName
Ich dachte das SProject::m_sName so etwas in der Art wie this (wie in z.B. C# in Klassen benutzt wird) ist.
-
KreativerName schrieb:
Danke für die Antwort manni66.
manni66 schrieb:
Wozu definierst du einen Destruktor
Das kann ich dir nicht sagen. Ich dachte (denke immer noch), dass eine Klasse einen Destruktor besitzen muss.
Das ist auch nicht ganz falsch, man muss sich schon sehr anstrengen, um eine Klasse zu erzeugen, die keinen Destruktor braucht. Aber weil das so ist, wird ein Destruktor bei Bedarf automatisch erzeugt. Siehe:
https://en.wikipedia.org/wiki/Special_member_functions
Diese automatisch erzeugten Funktionen haben dann die gleiche Funktionalität, als wenn du diese Funktionen selber leer definiert hättest (was in aller Regel auch korrekt ist). Es hat aber allerlei Vorteile, wenn man diese Funktionen nicht unnötig selber definiert und damit ist nicht nur Schreibfaulheit gemeint. Der Compiler kann allerlei Optimierungen vornehmen, wenn er mit Sicherheit weiß, dass der automatisch erzeugte Destruktor benutzt wird und keine benutzerdefinierte Funktion (in der er mit allem möglichen rechnen müsste).manni66 schrieb:
Wozu der leere Konstruktor?
Ist es sinnvoller einen Konstruktor mit vorgegebenen Parameterwerten zu definieren?
Jain. Für den Konstruktor gilt das gleiche wie oben für den Destruktor gesagt. Wenn er sowieso leer ist, dann kannst und solltest du ihn dir auch sparen.
Allgemein sollte ein Objekt aber nach der Erzeugung mittels des Konstruktors voll einsatzbereit sein. Das heißt, es sollte nicht nötig sein, noch weitere Init-Funktionen oder ähnliches aufzurufen, bevor man mit dem Objekt arbeiten kann. Das Beispiel hier ist zu abstrakt, als dass ich mit Sicherheit sagen könnte, ob hier ein komplexer, selbstdefinierter Konstruktor nötig wäre oder nicht. Deine Defaultparameter sehen aber jedenfalls eher unsinnig aus. Defaultparameter sind nicht als Platzhalter gedacht!Wann benutzt man also Initialisierungslisten und wann normale Konstruktoren? Oder nehme ich immer
Initialisierungslisten?Normalerweise immer Initialisierungslisten. Jemand mit mehr Zeit als ich mag vielleicht ein exotisches Beispiel ersinnen, bei dem diese Faustregel verletzt wird.
manni66 schrieb:
Warum verwendest du SProject::m_sName statt m_sName
Ich dachte das SProject::m_sName so etwas in der Art wie this (wie in z.B. C# in Klassen benutzt wird) ist.
Es ist einfach überflüssig. Innerhalb von Methodendefinitionen der Klasse ist das alles weitgehend identisch, egal ob mit Klassennamen, this, oder einfach gar nichts vor dem Bezeichner. Da kann man auch einfach die kürzeste Schreibweise wählen, außer man hat gewichtige Gründe, dies nicht zu tun.
-
Danke für die Antwort SeppJ!
Nochmal eine Frage zu meinem ersten Post. Ich speicher momentan die Instanzen von der Klasse SProject in einem Vector. Macht man das auch so? Oder benutzt man eher eine list?
-
KreativerName schrieb:
Macht man das auch so?
Man macht, was man benötigt. Wenn man einem Container benötigt, nimmt man std::vector, es sei denn, ein anderer passt besser. Dabei sollte man "ist schneller" als Argument genau prüfen.
-
manni66 schrieb:
KreativerName schrieb:
Macht man das auch so?
Man macht, was man benötigt. Wenn man einem Container benötigt, nimmt man std::vector, es sei denn, ein anderer passt besser. Dabei sollte man "ist schneller" als Argument genau prüfen.
Ok.
Danke an euch beiden für die Antworten.
-
Hinweis: Eine list passt so gut wie nie.