Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

01.07.2007, 18:57

Exception &e?

Weshalb ist es nötig den Typ exception in einer Referenz zu erzeugen?
Beispiel:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
vector vDaten(3);
try
{
v.Daten.at(0);

v.Daten.at(1);

// Wirft eine Exceptiona aus

vDaten.at(3);
}
catch (exception &e)
{
blabla
}


Und wieso brauche ich kein "throw"?
Hoffe ihr könnt mir behilflich sein.
"Wenn es keine Milch gäbe, würde ich auf Kaffee verzichten."

big_muff

Alter Hase

Beiträge: 460

Wohnort: Schweiz

Beruf: Informatikstudent (4. Semester)

  • Private Nachricht senden

2

01.07.2007, 19:48

Die Exception wird ja in vDaten.at(3) geworfen, das steht doch im Kommentar. Also steht auch in dieser Funktion das throw.

Und was du mit "den Typ exception in einer Referenz erzeugen" meinst versteh ich nicht...
Nur Idioten halten Ordnung, ein Genie beherrscht das Chaos.[size=7]

[/size]HardFate - Ein Start, Ein Ziel, Viele Wege[size=7]

[/size]Ein Mitglied der VEGeiCoUndGraSonMaWiGeS Bewegung.

3

01.07.2007, 20:21

Erstmal danke für die Antwort.-> Darüber war ich mir nämlich nicht im klaren.
Weshalb wir der "&"-Adressoperator benutzt für &e.

Wenn ich doch den Adressoperator bei einer deklaration verwende handelt es sich um eine Referenz.
"Wenn es keine Milch gäbe, würde ich auf Kaffee verzichten."

grek40

Alter Hase

Beiträge: 1 491

Wohnort: Dresden

  • Private Nachricht senden

4

01.07.2007, 20:22

Es ist ja so, dass man, wenn man einfach nur exception e schreibt eine Kopie der Exception erstellt, was absolut unnötig ist. außerdem gibt ees die Möglichkeit, eine Exception zu bearbeiten und weiter zu leiten:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
try {
// ...

}
catch( exception& e )
{
// e verändern

throw(); // die geänderte Exception weiter zu anderen catchblöcken schicken

}

Wenn man in diesem Beispiel keine Referenz nimmt erhält der nächste catchblock nicht die geänderte sondern die Anfangsinformation.

// Die exception wird bereits beim ersten throw erstellt - es reicht also, eine referenz auf die bestehende Exception zu holen!

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

5

01.07.2007, 20:23

Zum einen um unnötige Objektkopien zu vermeiden, zum anderen das du den Status von Exceptions ändern kannst bei weiterleitung und zuletzt, der wichtigste Grund, um Objektslicing zu vermeiden.

@grek40: Wenn mans genau nimmt so: ;)

C-/C++-Quelltext

1
2
3
4
5
6
7
8
try {
// ...

}
catch( exception& e )
{
// e verändern

throw; // die geänderte Exception weiter zu anderen catchblöcken schicken

}
@D13_Dreinig

6

01.07.2007, 20:25

Danke!

Nun, im nachhinein ist es ja nur logisch! Wäre ohne auch, jedoch nicht auf die Idee gekommen. Danke :D
"Wenn es keine Milch gäbe, würde ich auf Kaffee verzichten."

grek40

Alter Hase

Beiträge: 1 491

Wohnort: Dresden

  • Private Nachricht senden

7

01.07.2007, 20:49

Mist, so oft mach ich das nich mit dem weiterleiten^^

Was ist eigentlich dieses Objektslicing das du erwähnt hast? (evtl. falsch geschrieben, da Google den Begriff nicht zu kennen scheint)

// Edit... habs gefunden, is jetzt klar

David_pb

Community-Fossil

Beiträge: 3 886

Beruf: 3D Graphics Programmer

  • Private Nachricht senden

8

01.07.2007, 21:10

Für alle anderen:

Angenommen man hat zwei Klassen (A und B), wobei B eine spezialsisierte Variante von A ist:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
struct A
{
    int x;

    explicit A( int val )
        : x( val )
    {}

    virtual void foo() const
    {
        std::cout << "A::foo()\n";
    }
};

struct B : public A
{
    explicit B( int val )
        : A( val )
    {}

    void foo() const
    {
        std::cout << "B::foo()\n";
    }
};


Nun gibt es z.B. eine Funktion die ein Objekt vom Typ A als Parameter an nimmt:

C-/C++-Quelltext

1
2
3
4
void test( A obj )
{
    obj.foo();
}


Diese Funktion nimmt aber nicht nur A Objekte an, sondern auch B Objekte können ohne weiteres übergeben werden:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
int main()
{
    A obj1( 10 );
    B obj2( 20 );

    test( obj1 );
    test( obj2 );

    std::cin.get();
}


Die Ausgabe ist nun folgende:

Zitat


A::foo()
A::foo()


Also nicht unbedingt das was gewollt war.

Mit anderen Worten: Alles was ein B-Objekt ausmacht wird also abgeschnitten und wir können nurnoch mit einem A-Objekt arbeiten.

Abhilfe verschaffen hier Referenzen oder Zeiger (Referenzen als C++ Weg ;)).

C-/C++-Quelltext

1
2
3
4
void test( const A& obj )
{
    obj.foo();
}


Zitat


A::foo()
B::foo()


Und schon klappts auch mit den Nachbarn! :-)
@D13_Dreinig

Werbeanzeige