2016-04-21 9 views
2

Angenommen, wir haben eine abstrakte Klasse Vehicle genannt:virtuelle Methode überschreibt in C++

class Vehicle { 
    virtual bool raceWith(Vehicle *anotherVehicle) = 0; 
}; 

Und wir haben seine Subklassen Bicycle und Car:

// forward declaration 
class Car; 

class Bicycle : public Vehicle { 
    virtual bool raceWith(Vehicle *anotherVehicle) { 
     throw SomeExceptionClass(); 
    } 

    virtual bool raceWith(Car *anotherVehicle) { 
     return true; 
    } 

    virtual bool raceWith(Bicycle *anotherVehicle) { 
     return false; 
    } 
}; 

Doch dieser Code-Block wirft SomeExceptionClass:

Was zu tun er Re? Ermöglicht C++ nicht, polymorphe Methoden auf diese Weise zu verwenden?

Jede Hilfe wird geschätzt. Vielen Dank.

EDIT: Es wird auch gut sein, eine Antwort mit dynamic_cast<> und decltype Varianten zur Verfügung stellen?

Antwort

4

Im Folgenden wird Rennen ein Bicycle mit einem Vehicle:

Vehicle *aBicycle = new Bicycle(); 
Vehicle *aCar = new Car(); 

aBicycle->raceWith(aCar); 

Um eine Bicycle mit einer Car zu fahren, müssen wir den doppelten Versand verwenden.

Um Double-Dispatch Arbeit zu machen verwenden wir den this Zeiger die nächste Funktion aufrufen, so dass der zweite virtuelle Aufruf an die richtige Art von Fahrzeug lösen können:

class Car; 
class Bicycle; 

class Vehicle { 
public: 
    virtual bool raceWith(Vehicle& anotherVehicle) = 0; 
    virtual bool raceWith(Bicycle& anotherVehicle) = 0; 
    virtual bool raceWith(Car& anotherVehicle) = 0; 
}; 


class Bicycle : public Vehicle { 
public: 
    virtual bool raceWith(Vehicle& anotherVehicle) override 
    { 
     //throw std::exception(); 
     return anotherVehicle.raceWith(*this); 
    } 

    virtual bool raceWith(Car& anotherVehicle) 
    { 
     return true; 
    } 

    virtual bool raceWith(Bicycle& anotherVehicle) 
    { 
     return false; 
    } 
}; 

class Car : public Vehicle { 
public: 
    virtual bool raceWith(Vehicle& anotherVehicle) override 
    { 
     return true; 
    } 

    virtual bool raceWith(Car& anotherVehicle) override 
    { 
     return true; 
    } 

    virtual bool raceWith(Bicycle& anotherVehicle) override 
    { 
     return false; 
    } 

}; 

int main() 
{ 

    Vehicle *aBicycle = new Bicycle(); 
    Vehicle *aCar = new Car(); 

    aBicycle->raceWith(*aCar); 
} 

Notiere die return anotherVehicle.raceWith(*this);, die den zweiten virtuellen durchführen wird Anruf.

  • main();
  • Bicycle::raceWith(Vehicle& anotherVehicle);
  • Car::raceWith(Bicycle& anotherVehicle);
  • mit dem Einsatz

Das folgende ist das gleiche Programm, aber Festhalten von:

Die Funktionen werden dann in dieser Reihenfolge genannt Zeiger und Ausnahmen wie in der Frage:

+0

Was ist Doppelversand? – Leviathlon

+1

@Leviathlon double virtual dispatching ist die Fähigkeit, die korrekte Implementierung abhängig vom dynamischen Typ von ** two ** -Objekten aufzurufen. C++ bietet nur ein einziges virtuelles Dispatching auf "this". Was flatmouse hier beschreibt, ist als Visitor-Muster bekannt und verwendet zweimaliges Dispatching, um eine doppelte Disposition zu erreichen. – Quentin

+0

Dies löste das Problem. So eine großartige Antwort. Vielen Dank für die Aufmerksamkeit. – Leviathlon

1

von

Vehicle *aBicycle = new Bicycle(); 
aBicycle->raceWith(aCar); 

Die Art der aCar tun ist Vehicle (typeid(aCar).name()), so dass Ihr Compiler die Methode mit Fahrzeug ruft.

aBicycle->raceWith(static_cast<Car*>(aCar)); 
aBicycle->raceWith(dynamic_cast<Car*>(aCar)); 

Versuchen Was, warum static_cast oder dynamic_cast, Sie auf SO in diesem Beitrag aussehen kann: Regular cast vs. static_cast vs. dynamic_cast

+0

Es war es tut mir leid, ich habe es vermisst. – Leviathlon

+0

Ich hatte gesagt ** Unterklasse **. Bitte geben Sie dies nicht als Antwort an. – Leviathlon

+0

In der objektorientierten Programmierung hat es eine Definition. Es unterscheidet sich leider nie. – Leviathlon

1

Versuchen Sie dies, können Sie dynamische Besetzung verwenden, um den Typ für Unterklasse zu erkennen. Wenn Sie virtual bool raceWith(Vehicle *anotherVehicle) als Methode beibehalten, werden virtual bool raceWith(Car *anotherVehicle) und virtual bool raceWith(Bicycle *anotherVehicle) niemals ohne Casting ausgeführt, da anotherVehicle ein Fahrzeugtyp obj ist. Hoffe wird helfen :)

#include <iostream> 
using namespace std; 
class Car; 
class Bicycle; 

class Vehicle { 
    public: 
    //virtual bool raceWith(Vehicle *anotherVehicle) = 0; 
    virtual bool raceWith(Car *anotherVehicle) = 0; 
    virtual bool raceWith(Bicycle *anotherVehicle) = 0; 
}; 

class Bicycle : public Vehicle { 
    /*virtual bool raceWith(Vehicle *anotherVehicle) { 
     throw SomeExceptionClass(); 
    }*/ 
    virtual bool raceWith(Car *anotherVehicle) { 
     cout << "will print" << endl; 
     return true; 
    } 
    virtual bool raceWith(Bicycle *anotherVehicle) { 
     return false; 
    } 
}; 
class Car : public Vehicle { 
    /*virtual bool raceWith(Vehicle *anotherVehicle) { 
     throw SomeExceptionClass(); 
    }*/ 
    virtual bool raceWith(Car *anotherVehicle) { 
     return true; 
    } 

    virtual bool raceWith(Bicycle *anotherVehicle) { 
     return false; 
    } 
}; 
int main() 
{ 
    Vehicle *aBicycle = new Bicycle(); 
    Vehicle *aCar = new Car(); 

    if (dynamic_cast<Bicycle*>(aCar) != NULL) { 
     std::cout << "Race with A Bicycle" << std::endl; 
     aBicycle->raceWith(static_cast<Bicycle*>(aCar)); 
    } 
    else if (dynamic_cast<Car*>(aCar) != NULL) { 
     std::cout << "Race with A Car" << std::endl; 
     aBicycle->raceWith(static_cast<Car*>(aCar)); 
    } 
    else { 
     //throw SomeExceptionClass(); 
    } 

    //aBicycle->raceWith(aCar); 

    return 0; 
} 
+0

Ich denke, für das, was Sie hier erreichen wollen, hilft google -Visitor Design Pattern Ihnen mehr – JaNL