ein polymorphes Problem



  • Hallo.

    Ich hab ein schwer zu ergoogelndes Problem mit Polymorphie. Vielleicht kann mir jemand weiterhelfen. Folgender Beispiel-Code:

    #include <iostream>
    using namespace std;
    
    class Data
    {
    	public:
    		virtual ~Data() {}
    		int x;
    };
    
    class Verifier
    {
    	public:
    		virtual bool verify(Data* d) = 0; 
    };
    
    class specialData : public Data
    {
    	public:
    		int y;
    };
    
    class specialVerifierA : public Verifier
    {
    	public:
    		bool verify(Data* d)
    		{
    			cout << ":-/ specialVerifierA "<< d->x <<" >= 0 ?"<<endl;
    			return (d -> x >= 0);
    		}
    		bool verify(specialData* s)
    		{
    			cout << ":-) specialVerifierA "<< s->x <<" >= 0 && " << s->y << " >= 0 ?"<<endl;
    			return (s -> x >= 0 && s -> y >= 0);
    		}
    };
    
    class specialVerifierB : public Verifier
    {
    	public:
    		bool verify(Data* d)
    		{
    			cout << ":-/ specialVerifierB "<< d->x <<" < 100 ?"<<endl;
    			return (d -> x < 100);
    		}
    		bool verify(specialData* s)
    		{
    			cout << ":-) specialVerifierB "<< s->x <<" < 100 && " << s->y << " < 100 ?"<<endl;
    			return (s -> x < 100 && s -> y < 100);
    		}
    };
    
    class Checker
    {
    	private:
    		Verifier* v;
    		Verifier* w;
    
    	public:
    		Checker(Verifier* vv, Verifier* ww) {v = vv; w = ww;}
    		bool check(Data* d)
    		{
    			specialData* s = dynamic_cast<specialData*>(d);
    			if(s)
    			{
    				cout << "checking specialData" << endl;
    				return (v -> verify(s) && w -> verify(s));
    			}
    			else
    			{
    				cout << "checking Data" << endl;
    				return (v -> verify(d) && w -> verify(d));
    			}
    		}
    };
    
    int main()
    {
    	specialVerifierA A;
    	specialVerifierB B;
    
    	Checker C(&A, &B);
    	specialData S;
    	S.x = 23;
    	S.y = 42;
    	cout << ( C.check(&S) ? "jo" : "ne" ) << endl;
    
    	return 0;
    }
    

    Die Ausgabe ist:

    checking specialData
    :-/ specialVerifierA 23 >= 0 ?
    :-/ specialVerifierB 23 < 100 ?
    jo
    

    Das bedeutet, er ruft beim check en immer die verify(Data* d) auf. Ich hätte aber gern, dass er die verify(specialData* s) aufruft - immerhin ist das zu- verify ende Objekt ja vom Typ specialData , wie die erste Zeile der Ausgabe verlauten lässt.

    Nun könnte ich für jeden von Data abgeleiteten Typ eine solche Zeile

    virtual bool verify(class specialData* d) {}
    

    in die Verifier Klasse einbauen, aber es gibt eine ganze Reihe solcher abgeleiteten Typen, und das macht irgendwie die schöne "Allgemeingültigkeit" des Codes kaput.

    Hat jemand Vorschläge, was ich alternativ tun könnte?

    Lars



  • Schau dir vielleicht mal den Visitor bzw. Double Dispatch Pattern an...



  • verify(Data*) und verify(specialData*) sind zwei vollkommen unabhängige Funktionen. Insbesondere hat verify(specialData*) in specialVerifier nichts mit verify(Data*) in Verifier zu tun. Deshalb wird sie gar nicht berücksichtigt. Darüber hinaus werden Funktionsüberladungen immer schon zur Compilezeit durch die statischen Typen der Objekte aufgelöst.

    Die Lösung ist aber einfach: teste in deinen specialVerifier::verify(data*), ob der Parameter nicht eigentlich ein specialData* ist und rufe in dem Fall die überladene Version manuell auf.



  • ipsec schrieb:

    Die Lösung ist aber einfach: teste in deinen specialVerifier::verify(data*), ob der Parameter nicht eigentlich ein specialData* ist und rufe in dem Fall die überladene Version manuell auf.

    Brilliant! 🙂 (Das lässt sich auf mein echtes Programm übertragen.) Ein Hoch auf das Forum! 👍


Anmelden zum Antworten