Seite 1 von 1

Exception-cast..? [solved]

Verfasst: 14.02.2012, 09:33
von joggel
Hi ho,

ich spiele gerade etwas rum, und zwar mit exceptions.
Ich habe folgenden Code (Ich will mal nicht jede Klasse aufschreiben, ich versuche aussagekräftige Namen zu nehmen) :

Code: Alles auswählen

try
{
 throw ExceptionXYZ_DerivedFromExceptionBase(arg1,arg2,arg3); 
}
catch( ExceptionBase& exception ) // <== "ExceptionXYZ_DerivedFromExceptionBase" wird ja hier auf jeden Fall "gefangen"
{
 ExceptionXYZ_DerivedFromExceptionBase* exceptionXYZ( dynamic_cast<ExceptionXYZ_DerivedFromExceptionBase*>(&exception ) );
// der Cast funktioniert hier nicht!!
}
Genau... ich möchte gerne herausfinden, welcher Typ die Exception war. Ich könnte auch ein "catch" für jeden Exception-Typ schreiben, aber das will ich mal bewusst vermeiden.
Was mir spontan einfällt:
Einen eigenen cast schreiben, der anhand des Klassennamens prüft, ob der Cast funktioniert.
Allerdings stehe ich da wieder vor einem Problem:
Ich muss so oder so einen cast durchführen.
Mal etwas Code:

Code: Alles auswählen

T  my_dynamic_cast<T>( ExceptionBase* exception)
{
	if( T.getClassName() == exception->getClassName() )
	{
	  // hier müsste irgendetwas passieren, was aus "exception" eine Instanz von "T" macht, und zurueckgegeben wird
	}
}
Ist halt alles nur mal etwas rumgespiele und ich weiß auch garnicht, ob ich dabei alles richtig mache...

Re: Exception-cast..?

Verfasst: 14.02.2012, 09:46
von RazorX
Der dynamic_cast prüft die Polymorphie über die virtual tables. Wenn du also keine virtuelle Funktion durch die Hierarchie reichst, wird dynamic_cast immer nullptr zurückgeben.

Re: Exception-cast..?

Verfasst: 14.02.2012, 09:48
von joggel
Ok... das erklärt es.
Aber kann ich das irgendwie umgehen?
Also das ich doch auf irgendeinen Weg an den Typ und Informationen der gewurfenen Exception rankomme?

Re: Exception-cast..?

Verfasst: 14.02.2012, 09:58
von RazorX
AFAIK hast du in C++ nur die Möglichkeit über dynamic_cast + viruelle Methoden die Polymorphie zu überprüfen. Das Problem ist einfach, dass C++ keine Typüberwachung mitbringt, also im Speicher nicht drinsteht was für ein Typ das ist (wie z.B. in C#, Java). Du kannst natürlich sowas mit Klassennamen machen, ob es jedoch sinnvoller ist als stumpf eine virtuelle Methode zu definieren ist fragwürdig.

Re: Exception-cast..?

Verfasst: 14.02.2012, 10:02
von joggel
Mh... ok.
Das ist mistig... ich könnte zwar rausbekommen, um welche abgeleitete Klasse es sich handelt, aber an die konkreten Funktionen und Member der abgeleiteten Klasse komme ich nicht ran... verdammt!
Oder nur durch irgendwelche schrägen Umwege.
Naja, mal sehen was mir einfällt oder auch nicht ^^

Re: Exception-cast..?

Verfasst: 14.02.2012, 10:08
von RazorX
Naja so schwer ist das aber doch nicht.

Code: Alles auswählen

// Klassen 
class Foo : std::exception {
public:
    virtual ~Foo();
};

class Bar : public Foo{
public:
    virtual ~Bar();
};

// In der Methode
try {
   throw Foo();
} catch(std::exception& e) {
   Foo* myException = dynamic_cast<Foo*>(&e);
   if(myException != nullptr) {
        // Irgendwas
   } else {
        // Weitere Fälle
   }
}

Re: Exception-cast..?

Verfasst: 14.02.2012, 10:09
von joggel
Das funktioniert bei dir?
Bei mir funktioniert das nicht... deswegen hatte ich ja gefragt.
Ich benutze VS 2005 ( ja, noch kam ich nicht dazu umzusteigen! ).

Re: Exception-cast..?

Verfasst: 14.02.2012, 10:16
von Schrompf
Eigentlich müsste es wirklich reichen, den Destruktor der Basisklasse virtuell zu deklarieren. Das wäre dann die virtuelle Methode, weswegen der Compiler einen vtable anlegen müsste, womit dynamic_cast dann funktionieren sollte.

Re: Exception-cast..?

Verfasst: 14.02.2012, 10:20
von RazorX
Jo, kleiner Fehler. Muss natürlich von std::exception public erben^^

Das funktioniert, habs getestet:

Code: Alles auswählen

#include "stdafx.h"
#include <exception>
#include <iostream>

class Foo : public std::exception {
public:
	virtual ~Foo(){}
};

class Bar : public Foo{
public:
	virtual ~Bar(){}
};

// In der Methode
int _tmain(int argc, _TCHAR* argv[])
{
	try {
	   throw Foo();
	} catch(std::exception& e) {
	   Foo* myException = dynamic_cast<Foo*>(&e);
	   if(myException != nullptr) {
		   std::cout << "Foo" << std::endl;
	   } else {
			// Weitere Fälle
	   }
	}
	system("PAUSE");
	return 0;
}
Edit: nullptr ist ein neues Sprachfeature, stattdessen kannste natürlich NULL oder einfach 0 verwenden.

Re: Exception-cast..?

Verfasst: 14.02.2012, 10:22
von joggel
Oh, stimmt!
Gerade getestet.
Es funktioniert, sehr schön: danke!! :)
Hatte den Destructor nicht als virtual deklariert.

Re: Exception-cast..? [solved]

Verfasst: 14.02.2012, 10:46
von dot
joggel hat geschrieben:Genau... ich möchte gerne herausfinden, welcher Typ die Exception war. Ich könnte auch ein "catch" für jeden Exception-Typ schreiben, aber das will ich mal bewusst vermeiden.
Wieso? Genau das wäre imo die saubere Lösung.

Re: Exception-cast..? [solved]

Verfasst: 14.02.2012, 10:51
von joggel
dot hat geschrieben: Wieso? Genau das wäre imo die saubere Lösung.
Ja, das mache ich eigentlich auch immer so.
Aber mir ging es diesmal um was anderes und wollte mal was testen.
Und habe dabei einfach bei meinen Test-Klassen keine virtuellen Funktionen deklariert...
deswegen funktionierte der Cast nicht, und ich dachte, dass das mit den Casts bei Exception irgendwie anders läuft.
Also: Unwissenheit/Unachtsamkeit.