13 Stimmen

Behandlung einer Klasse mit einer langen Initialisierungsliste und mehreren Konstruktoren?

Ich habe ein (für mich) komplexes Objekt mit etwa 20 Datenelementen, von denen viele Zeiger auf andere Klassen sind. Für den Konstruktor habe ich also eine große, lange und komplexe Initialisierungsliste. Die Klasse hat außerdem ein Dutzend verschiedener Konstruktoren, die die verschiedenen Möglichkeiten widerspiegeln, wie die Klasse erstellt werden kann. Die meisten dieser initialisierten Elemente sind zwischen den verschiedenen Konstruktoren unverändert.

Meine Sorge dabei ist, dass ich jetzt einen großen Haufen kopierten (oder größtenteils kopierten) Codes habe, der, wenn ich der Klasse ein neues Mitglied hinzufügen muss, es möglicherweise nicht in jede der Konstruktorinitialisierungslisten schafft.

class Object 
{
    Object();
    Object(const string &Name);
    Object (const string &Name, const string &path);
    Object (const string &Name, const bool loadMetadata);
    Object (const string &Name, const string &path, const bool loadMetadata);
} 

Object::Object() :
    name(),
    parent_index (0),
    rowData (new MemoryRow()),
    objectFile (),
    rows (new MemoryColumn (object_constants::RowName, OBJECTID, object_constants::ROWS_OID)),
    cols (new MemoryColumn (object_constants::ColName, OBJECTID, object_constants::COLS_OID)),
    objectName (new MemoryColumn(object_constants::ObjName, STRING, object_constants::short_name_len, object_constants::OBJECTNAME_OID)),
    parent     (new MemoryColumn(object_constants::ParentName, STRING, object_constants::long_name_len, object_constants::PARENT_OID)),
    parentIndex (new MemoryColumn(object_constants::ParentIndex, OBJECTID, object_constants::PARENTINDEX_OID)),
    childCount (new MemoryColumn (object_constants::ChildCount, INTEGER, object_constants::CHILD_COUNT_OID)),
    childList (new MemoryColumn (object_constants::ChildList, STRING, object_constants::long_name_len, object_constants::CHILD_OID)),
    columnNames (new MemoryColumn (object_constants::ColumnNames, STRING, object_constats::short_name_len, object_constants::COLUMN_NAME)),
    columnTypes (new MemoryColumn (object_constants::ColumnTypes, INTEGER, object_constants::COLUMN_TYPE)),
    columnSizes (new MemoryColumn (object_constants::ColumnSizes, INTEGER, object_constants::COLUMN_SIZE))
{}

Dann wiederholen Sie die oben beschriebenen Schritte für die anderen Konstruktoren. Gibt es eine intelligente Art und Weise der Verwendung der Standard-Konstruktor für diese, dann ändern Sie die Ergebnisse für die anderen Konstruktoren?

2voto

aJ. Punkte 33220

Sie können ihren gemeinsamen Code in einer privaten init()-Mitgliedsfunktion teilen.

Ejemplo:

class Object
{
 public:
   Object(const string &Name);
   Object(const string &Name, const string &path);
   ...
 private:
   void init();
 };

 Object::Object(const string &Name)
 {
   init();
   ...
 }

 Object::Object(const string &Name, const string &path)
 {
   init();
   ...
 }

 void Object::init()
 {
//intialization stuff
   ...
 }

1voto

Cătălin Pitiș Punkte 13785

Zunächst einmal kommt es zu Speicherlecks, wenn Sie das Löschen der zugewiesenen Objekte nicht im Destruktor implementieren. Sie sollten also Ihren Destruktor definieren und die Objekte dort löschen.

Wenn Sie die Mitglieder wirklich dynamisch zuweisen müssen (ich empfehle nicht, wenn diese Klasse das Datenmitgliedobjekt besitzt), können Sie eine private Methode haben, die die gesamte Initialisierung vornimmt, und Sie können diese Methode von Ihren Konstruktoren aus aufrufen.

1voto

David Thornley Punkte 55244
Object (const string &Name = "", const string &path = "", const bool loadMetadata = false);

Dies wird nicht alle Ihre Probleme lösen (insbesondere gibt es keine Möglichkeit, den Konstruktor mit Name und loadMetaData darzustellen), aber es wird zumindest einige der Konstruktoren in einem zusammenfassen.

1voto

e.James Punkte 112528

Ich möchte vorausschicken, dass ich (natürlich) nicht die Details Ihres Systems oder die Zwänge kenne, die zu Ihren Designentscheidungen geführt haben.

Eine gute Faustregel lautet: Wenn eine Klasse anfängt, unruhig zu werden - etwa zu dem Zeitpunkt, an dem du anfängst, Fragen zu stellen, wie du damit umgehen sollst :) - ist es vielleicht an der Zeit, die Klasse in mehrere kleinere Unterklassen zu zerlegen.

Denken Sie daran, dass eine Klasse folgende Aufgaben hat eine Sache sehr gut . Wenn Sie anfangen, große Klassen zu haben, die versuchen, zu viele Dinge zu tun, entfernen Sie sich von gutem OO-Design.

1voto

chrish Punkte 2244

Ich würde verschiedene Factory-Methoden (statische Methoden) verwenden, die einen Smart-Ptr an Ihre Klasse zurückgeben würden. Die Namen der Fabrikmethoden würden auch dabei helfen zu dokumentieren, WARUM Sie all die verschiedenen Parameter benötigen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X