2016-04-28 8 views
0

Ich lerne C++. Ich habe eine Basisklasse, Base, und seine abgeleitete Klasse, Derived. Und sie sind push_back in std::vector<Base*> vec. Unter der Annahme vec[0] == &Base und vec[1] == &Derived kann ich die Funktion für und vec[1] ohne virtuelle Funktion wechseln. Der Code ist am Ende dieser Frage. Gibt es einen besseren Weg, es ohne virtuelle Funktion zu machen? Ich möchte reine Datenklassen und ich möchte Nichtmitgliedsfunktionen hinzufügen, um sie zu modifizieren, um zu vermeiden, Code von Datenklassen zu ändern. Vielen Dank.Gibt es eine bessere Möglichkeit, die Funktion ohne virtuelle Funktion zu wechseln?

class TypeInterface { 
public: 
    virtual int type(void) = 0; 
    virtual ~TypeInterface() {} 
}; 

class Base : public TypeInterface { 
public: 

    static constexpr int type_ = 1; 
    virtual int type(void) { 
     return type_; 
    } 

    virtual ~Base() {} 
}; 

class Derived : public Base { 
public: 

    static constexpr int type_ = 10; 
    virtual int type(void) { 
     return type_; 
    } 

    virtual ~Derived() {}; 
}; 

void Function(Base* ptr) { 
    std::cout << "function for Base" << std::endl; 
} 

void Function(Derived* ptr) { 
    std::cout << "function for Derived" << std::endl; 
} 

void SwitchFunction(int type, void* ptr) { 
    switch (type) { 
    case 1: { 
     Base* original_type_ptr = static_cast<Base*>(ptr); 
     Function(original_type_ptr); 
     break; 
    } 
    case 10: { 
     Derived* original_type_ptr = static_cast<Derived*>(ptr); 
     Function(original_type_ptr); 
     break; 
    } 
    default: 
     std::cout << "invalid type(=" << type << ")" << std::endl; 
    } 
} 

void test_function_selecter(void) { 

    Base b; 
    Derived d; 

    std::vector<Base*> vec; 

    vec.push_back(&b); 
    vec.push_back(&d); 

    for (auto e: vec) { 
     SwitchFunction(e->type(), e); 
    } 

} 
+1

Ihr Code hat ein undefiniertes Verhalten. Das sind einige böse Würfe. Idealerweise sollten Sie, wenn Sie nur C++ lernen, überhaupt keine Zeiger oder Umwandlungen verwenden. –

+1

Wie wäre es, die Funktion als Variable zu speichern? Sie können es statisch machen, wenn es für alle Instanzen verwendet wird. std :: function myFunc = [] (void) {// mach etwas} – Striker

+0

Danke, Kerrek SB. Ich habe versucht, herauszufinden, um was es sich bei Ihnen handelt, und ich nehme an, Sie befürchten vielleicht, dass ich eine falsche Kombination von Typ und Nichtigkeit verwenden kann *. In meinem Fall hat SwitchFunction (e-> type(), e) ein festes Format. Ich hoffe also, dass ich die falsche Kombination vermeiden kann. – mora

Antwort

1

Sie brauchen nicht 'type_' oder 'Typ int (void)' stattdessen 'typeid'

void SwitchFunction(Base* ptr) 
{ 
    auto&& type = typeid(*ptr); 
    if (type == typeid(Base)) 
     Function(dynamic_cast<Base*>(ptr)); 
    else if (type == typeid(Derived)) 
     Function(dynamic_cast<Derived*>(ptr)); 
    else std::cout << "invalid type(=" << type.name() << ")" << std::endl; 
} 

Leider wahrscheinlich diese Antwort Ihre Frage nicht richtig, da es 'Base' erfordert eine virtuelle Funktion zu haben (z. B. ein Destruktor, der im Allgemeinen empfohlen wird, virtuell zu sein, wenn Ihr Typ an Hierarchien beteiligt ist)

+0

Danke, Issac. Ich fürchte, ich konnte Ihnen meinen Standpunkt nicht sagen. Der Punkt ist, ich möchte Funktion hinzufügen, um Datenklasse zu behandeln, ohne die Datenklasse zu ändern. Wenn ich virtuelle Klasse verwende, muss ich der Datenklasse virtuelle Funktion hinzufügen (und ändern). Also virtueller Destruktor ist ok für mich. Vielen Dank für Ihre Lösung. Aber lass mich dich ein bisschen mehr fragen. Was ist Ihrer Ansicht nach besser oder gleich, was ist Ihr Weg oder mein Weg? – mora

+1

& mehr gibt es wahrscheinlich ungefähr das gleiche, aber wenn Sie wirklich interessieren, würde ich vorschlagen, es zu testen, persönlich würde ich nicht stören, es sei denn, die Anzahl der Typen, die Sie haben, ist wirklich groß, in diesem Fall kann die 'switch' Aussage ausführen 'if/else if' Anweisungen (Sie können 'switch' nicht mit 'typeid' verwenden), meine Lösung benötigt natürlich weniger Platz in Ihren Objekten, was wahrscheinlich wichtiger ist als kleinere Leistungsunterschiede. – Isaac

Verwandte Themen