2017-03-23 6 views
0

Ich habe eine Basisklasse und zwei abgeleitete Klassen. Jetzt möchte ich einen Vektor der Basisklasse erstellen. Wenn ich ein neues Element hinzufüge, prüft es, welche Klasse des neuen Elements. Aber in C++ gibt es keine Funktion wie instanceOf, also muss ich Variable type hinzufügen, um zu überprüfen. Hier mein Code.Distinc abgeleitete Klasse C++

class Element { 
public: 
    int type; 
    int getIndex() const { 
     return index; 
    } 

    void setIndex(int index) { 
     this->index = index; 
    } 

    const std::string& getMsg() const { 
     return msg; 
    } 

    void setMsg(const std::string& msg) { 
     this->msg = msg; 
    } 

    std::string toString() { 
     std::stringstream sbuf; 
     sbuf << "index: " << index << "\n"; 
     sbuf << "Message: " << msg << "\n"; 
     return sbuf.str(); 
    } 

private: 
    int index; 

    std::string msg; 

}; 

Zwei abgeleitete Klasse:

class This: public Element { 
public: 
    This():Element(1){} 
    ~This(); 

    const std::vector<std::string>& getArguments() const { 
     return arguments; 
    } 

    void setArguments(const std::vector<std::string>& arguments) { 
     this->arguments = arguments; 
    } 

    void add(std::string value) { 
     arguments.push_back(value); 
    } 

private: 
    std::vector<std::string> arguments; 


}; 

class That: public Element { 
public: 
    That():Element(2){} 
    ~That(); 

    const std::string& getThatVal() const { 
     return thatVal; 
    } 

    void setThatVal(const std::string& thatVal) { 
     this->thatVal = thatVal; 
    } 

private: 
    std::string thatVal; 


}; 

In einer anderen Klasse, möchte ich das Array von Element erstellen.

class Visitor { 
private: 
    int numOfThis = 0; 
    int numOfThat = 0; 
    std::vector<Element> vecEle; 

public: 
    void add(Element ele) { 
     vecEle.push_back(ele); 
     if (ele.type == 1) { 
      numOfThis++; 
     } else if (ele.type == 2) { 
      numOfThat++; 
     } 
    } 

    int getNumOfThat() const { 
     return numOfThat; 
    } 

    int getNumOfThis() const { 
     return numOfThis; 
    } 
}; 

Meine Frage ist, wie man damit besser umgehen? Gibt es ein Entwurfsmuster für diese Situation? Dank

+2

Auch wenn es in C++ "instanceof" gab, würde es hier nicht funktionieren, da Ihre Klassen nicht polymorph sind. Erfahren Sie mehr darüber und speichern Sie Zeiger, die in einem Vektor basieren. Wenn Sie versuchen, zu "dynamic_cast" zu wechseln, wird Ihnen angezeigt, um welchen Typ es sich bei jedem Element handelt. – DeiDei

+0

Wenn Sie nach dem Typ des Objekts wechseln müssen ... Es gibt ein Designproblem. Benutze die Objekte immer richtig ihre Typen. Wenn Sie die Elemente der Liste umwandeln möchten, möchten Sie einen spezifischeren Typ verwenden, den Sie auf eine niedrigere Ebene von Abstraktionen anwenden können. Es wird ein Code-Geruch genannt. Es gibt viele Design-Muster, um diese Gerüche zu verschwinden. Lesen Sie einige Bücher zu diesem Thema. –

Antwort

4

Sie können Zeiger speichern, anstatt Objekte in Ihrem Vektor, wie:

std::vector<Element *> vecEle; 

Dann können Sie dynamic_cast verwenden, um festzustellen, welche abgeleiteten Klasse Typ Ihres Zeiger ist.

// dynamic_cast will try to convert pointer of base class to derived class, 
// and return NULL on fail 
Element *pElem= vecEle[0]; // you can traverse your vector if needed 
if (This *pThis = dynamic_cast<This *>(pElem)) { 
    // object is This type 
} else if (That *pThat = dynamic_cast<That *>(pElem)) { 
    // object is That type 
} 
1

Klasse Element sollte eine Basisklasse sein, eine rein virtuelle Funktion bezeichnet, enthaltend d.h. VisitElement(Visitor* visitor).

Die Klasse Visitor hat nichts mit der Klasse zu tun, die Sie in Ihrem Code beschrieben haben. Sie ist tatsächlich als das Entwurfsmuster Visitor implementiert. Das bedeutet, es überladene Funktionen

void Visit(This* thisElem) {thisElem->VisitElement(this)}

und

void Visit(That* thatElem){thatElem->VisitElement(this)}

Diese Besucher Klasse enthält auch int counterThis und int counterThat enthalten. Dies ist die Implementierung für VisitElement in der Klasse ist so einfach wie

VisitElement(Visitor* visitor){ visitor->counterThis++;}

In Klasse, die die Implementierung für VisitElemnt so einfach wie

VisitElement (Visitor* visitor){ visitor->counterThat++;}

Und schließlich, um Sie tatsächlich zu zählen müssen Schleife über Ihren Vektor der Basisklasse Element Zeiger und auf jeden Zeiger in der Vektor-Aufruf visitor->Visit(elemFromBector) enthalten. Sobald die Schleife beendet ist, können Sie das Besucherobjekt für die zwei benötigten Ints abfragen. Denken Sie daran, dass diese Lösung Polymorphismus- und Besucherdesignmuster sowie einige Kapselungsprinzipien beinhaltet, die Sie in Ihrem ursprünglichen Code übersehen zu haben scheinen.

Verwenden Sie nicht dynamic_cast es ist innecient und es sollte nicht in jedem Produktionscode sein. Wenn Sie denken, dass Sie dynamic_cast brauchen, denken Sie noch einmal nach, weil etwas mit Ihrem Code nicht stimmt. Beste Ratschläge lesen Sie über Polymorphismus, Kapselung und Besucher Designmuster und Sie sollten in der Lage sein, meine Logik sehr leicht zu verstehen.

+0

Danke für die Bearbeitung Ich habe es aus meiner Zelle gemacht und hatte eine harte Zeit damit. – Calin

+0

Hier ist kein Besuchermuster erforderlich. "Sollte" ist viel zu string. – ROX

Verwandte Themen