Der Ausdruck muss einen Klassentyp aufweisen



  • Danke für die Hilfe!!

    Hätte ich allerdings Parameter in meinem Konstruktor, dann brauch ich ja die Klammern, oder?

    Daher dachte ich, wenn ich keine Parameter habe, dann mache ich leere Klammern... 😉

    Und wo wir grad bie Konstruktoren sind... Worin liegt denn der Unterschied zu meiner Variante oben und einer à la:

    Tier elefant = new Tier()

    Vielen Dank!!!



  • blub85 schrieb:

    Hätte ich allerdings Parameter in meinem Konstruktor, dann brauch ich ja die Klammern, oder?

    Richtig.

    blub85 schrieb:

    Daher dachte ich, wenn ich keine Parameter habe, dann mache ich leere Klammern... 😉

    Tja, falsch gedacht. :p

    blub85 schrieb:

    Worin liegt denn der Unterschied zu meiner Variante oben und einer à la:
    Tier elefant = new Tier()

    Hier wird eine Instanz im Freispeicher (Heap) abgelegt. Das ist dann manuelle Speicherverwaltung, und du musst das, was du mit new anforderst, wieder mit delete freigeben, ansonsten hast du ein Speicherleckt. (so sollte man es nicht machen)
    Bei der anderen Variante wird die Instanz auf dem Stack abgelegt. Der angeforderte Speicherplatz wird automatisch wieder freigegeben, da RAII. (so wird's gemacht)



  • Alles klar.. Vielen Dank!

    Worin liegt denn der Unterschied zw.

    Objekt.Methode() und Objekt->Methode() ?

    Das hängt doch mit dem oben genannten zusammen oder?



  • blub85 schrieb:

    Worin liegt denn der Unterschied zw.

    Objekt.Methode() und Objekt->Methode() ?

    Um es ganz grob zu sagen:

    Wenn du mit einem Zeiger auf Member einer Klasse zugreifen willst, funktioniert nicht der punkt-Operator (da es ja keine Referenz ist sondern ein Zeiger).

    Das bedeutet, du musst zuerst den Zeiger dereferenzieren, bevor du auf Member zugreifen kannst. Nun funktioniert aber folgendes nicht:

    *Zeiger.Funktion();
    

    Denn der Punkt-Operator wird zuerst ausgewertet. Also müsstest du die Dereferenzierung in Klammern setzen:

    (*Zeiger).Funktion();
    

    Was sehr hässlich ist. Also, statt obiges zu schreiben, hat man das eingeführt:

    Zeiger->Funktion();
    


  • Ah okay.. Super, ist super hilfreich für mich, was ihr hier grad alles postet...! Danke!

    Zwei Fragen hab ich gerade noch im Kopf:

    1. angenommen ich hab ne Klasse foo und erstelle mir ein Objekt davon, gibt es ja zwei Möglichkeiten:

    Foo fooInstanz1;
    

    und

    Foo fooInstanz2 = new Foo();
    

    Mit Stack und Heap haben wir ja vorhin schon gehabt.

    fooInstanz1 und fooInstanz2 sind aber jeweils Refernzen auf das Objekt, oder? Keine Zeiger o.Ä.

    und 2.
    Operatorüberladung. Hab ich soweit kapiert. Aber warum arbeite ich mit hierbei immer mit dem Referenzierungsoperator (in den Parametern)? Egal welche Beispiele ich mir hierzu anschaue, immer kommt der Operator vor, z.B.:

    Foo Foo::operator&(const Foo& a)
    {
    ...
    }
    

    Danke!!



  • blub85 schrieb:

    1. angenommen ich hab ne Klasse foo und erstelle mir ein Objekt davon, gibt es ja zwei Möglichkeiten:

    Foo fooInstanz1;
    

    und

    Foo fooInstanz2 = new Foo();
    

    Nein. Das erste ist richtig, das zweite ist falsch. Frag einfach mal deinen Compiler.

    blub85 schrieb:

    und 2.
    Operatorüberladung. Hab ich soweit kapiert. Aber warum arbeite ich mit hierbei immer mit dem Referenzierungsoperator (in den Parametern)? Egal welche Beispiele ich mir hierzu anschaue, immer kommt der Operator vor, z.B.:

    Foo Foo::operator&(const Foo& a)
    {
    ...
    }
    

    In deinem Beispiel dient es lediglich dazu, dir eine (potentiell teure) Kopie zu sparen.



  • blub85 schrieb:

    Foo fooInstanz2 = new Foo();
    

    Das ginge nur, wenn es einen Konstruktor von Foo gäbe, der (nur!) einen Zeiger auf Foo nimmt. Sonst müsste entweder fooInstanz2 ein Zeiger sein, oder der RValue new Foo dereferenziert werden.



  • Hacker schrieb:

    Du kannst auch z. B. Copy&Swap benutzen.

    Was hat denn Copy&Swap mit Foo Foo::operator&(const Foo&) zu tun?



  • Caligulaminus schrieb:

    Hacker schrieb:

    Du kannst auch z. B. Copy&Swap benutzen.

    Was hat denn Copy&Swap mit Foo Foo::operator&(const Foo&) zu tun?

    Ouh, ich dachte da steht operator=(... 😃



  • blub85 schrieb:

    fooInstanz1 und fooInstanz2 sind aber jeweils Refernzen auf das Objekt, oder? Keine Zeiger o.Ä.

    Nein. fooInstanz1 ist eine Instanz vom Typ Foo . Und zweiteres geht so nicht, weil new einen Zeiger auf den angeforderten Speicherbereich zurückgibt, sprich, du brauchst für Variante 2 einen Zeiger.

    blub85 schrieb:

    Aber warum arbeite ich mit hierbei immer mit dem Referenzierungsoperator (in den Parametern)?

    😕 Den Adressoperator zu überladen macht nur wenig Sinn, außer du willst verbieten, dass ein Zeiger auf eine Instanz deiner Klasse zeigen kann... und selbst das macht doch nur wenig Sinn.



  • Gugelmoser schrieb:

    blub85 schrieb:

    fooInstanz1 und fooInstanz2 sind aber jeweils Refernzen auf das Objekt, oder? Keine Zeiger o.Ä.

    Nein. fooInstanz1 ist eine Instanz vom Typ Foo . Und zweiteres geht so nicht, weil new einen Zeiger auf den angeforderten Speicherbereich zurückgibt, sprich, du brauchst für Variante 2 einen Zeiger.

    blub85 schrieb:

    Aber warum arbeite ich mit hierbei immer mit dem Referenzierungsoperator (in den Parametern)?

    😕 Den Adressoperator zu überladen macht nur wenig Sinn, außer du willst verbieten, dass ein Zeiger auf eine Instanz deiner Klasse zeigen kann... und selbst das macht doch nur wenig Sinn.

    Design-Regel: Es gibt Operatoren, die man nicht überladen sollte.



  • Hacker schrieb:

    Design-Regel: Es gibt Operatoren, die man nicht überladen sollte.

    Designregel gebrochen: PI schreibt eine Lambda-Lib, in der &_0 ein gültiger Lambda-Ausdruck ist. Deal with it.


Anmelden zum Antworten