[gelöst] Konstruktor kann nicht aufgerufen werden



  • es wurde schon alles machbare gesagt, eigentlich.
    du hast keinen passenden operator= (zuweisungsoperator) für deine klasse implementiert oder ihn verdeckt/verboten.

    int main()
    {
        FreeCamera _freeCamera;  //geht, d.h. du hast einen default konstruktor
        _freeCamera = FreeCamera(/*Parameter*/); // geht nicht, sagst du, daher keine zuweisungsoperator
    
        FreeCamera _fC = FreeCamera(/*Parameter*/); // daraus lässt sich schliessen, dass dein kopierkonstruktor vorhanden ist
    }
    

    das sind meine mutmaßungen, da kannst du was zu sagen...



  • Skym0sh0 schrieb:

    mal so dazwischen was offtopic:
    wie geht man eigentlich mit einer referenz als member um?
    aber im zuweisungsoperator? wie macht man das da?

    Ich denke mal, man verbietet ihn. Ansonsten handelt man sich ja nur Inkonsistenzen ein, wenn man nur den einen Teil des Objekts kopiert, den anderen Teil aber nicht.


  • Mod

    kraftkornbrot schrieb:

    @ camper:
    wow, bist du immer so freundlich zu neulingen?

    ja, wobei ich nicht zwischen Neulingen und anderen unterscheide.

    kraftkornbrot schrieb:

    wie geht man eigentlich mit einer referenz als member um?
    ok, man initialisiert sie im construktor. im kopier konstruktor ist das ja auch gut möglich, da ja ein neues objekt erstellt wird und sowas wie die initialisierungsliste gibts auch.
    aber im zuweisungsoperator? wie macht man das da?

    Refernzen als Member sind fast immer ein Designfehler, sie bieten gegenüber konstanten Zeigern keine Vorteile (Syntax ist irrelevant, schliesslich ist die Referenz nicht public), dafür mehrere Nachteile:
    - man kann keine Zeiger-auf-Member bilden,
    - es gilt nicht mehr sizeof(Member1)+sizeof(Member2)+... <= sizeof(Klasse)

    Im Übrigen ist ein const bei Membern meist auch fehl am Platz.

    Sinnvoll sind Memberreferenzen eigentlich nur bei Dingen wie Proxyobjekten. Kein Wunder, schliesslich ist ja ein Proxy im Prinzip so etwas wie eine Referenz. Und dann stimmt die Semantik der compilergenerierten Funktionen plötzlich wieder.



  • ok, sowas dachte ich mir nämlich.
    ganz unter uns, ich hab noch nie referenzen als member gebraucht, nur als parameter bei funktionen



  • camper schrieb:

    Refernzen als Member sind fast immer ein Designfehler, sie bieten gegenüber konstanten Zeigern keine Vorteile (Syntax ist irrelevant, schliesslich ist die Referenz nicht public), dafür mehrere Nachteile:
    - man kann keine Zeiger-auf-Member bilden,
    - es gilt nicht mehr sizeof(Member1)+sizeof(Member2)+... <= sizeof(Klasse)

    Ich stimme zu, dass Referenzmember nur selten verwendet werden sollten, allerdings bin ich der Meinung, dass deine Nachteile in den meisten Fällen irrelevant sind. Oder wann spielt die sizeof -Bedingung so im Code eine Rolle?

    Ein kleiner Vorteil von Referenzen ist, dass man deutlich macht, dass der Verweis nicht auf NULL zeigt, und dies auch vom Compiler prüfen lässt. Hängt aber vom Stil ab. Früher habe ich ab und zu Referenzen bei Funktoren verwendet, jedoch wird dann der Zuweisungsoperator nicht generiert, daher tendiere ich zu Zeigern.

    camper schrieb:

    Im Übrigen ist ein const bei Membern meist auch fehl am Platz.

    D.h. du würdest doch nicht konstante Zeiger, sondern veränderliche Zeiger als Alternative zu Referenzen vorschlagen? In dem Fall käme wieder der Nachteil zum Tragen, dass keine Initialisierung erzwungen wird.


  • Mod

    Nexus schrieb:

    camper schrieb:

    Refernzen als Member sind fast immer ein Designfehler, sie bieten gegenüber konstanten Zeigern keine Vorteile (Syntax ist irrelevant, schliesslich ist die Referenz nicht public), dafür mehrere Nachteile:
    - man kann keine Zeiger-auf-Member bilden,
    - es gilt nicht mehr sizeof(Member1)+sizeof(Member2)+... <= sizeof(Klasse)

    Ich stimme zu, dass Referenzmember nur selten verwendet werden sollten, allerdings bin ich der Meinung, dass deine Nachteile in den meisten Fällen irrelevant sind. Oder wann spielt die sizeof -Bedingung so im Code eine Rolle?

    Ein kleiner Vorteil von Referenzen ist, dass man deutlich macht, dass der Verweis nicht auf NULL zeigt, und dies auch vom Compiler prüfen lässt. Hängt aber vom Stil ab. Früher habe ich ab und zu Referenzen bei Funktoren verwendet, jedoch wird dann der Zuweisungsoperator nicht generiert, daher tendiere ich zu Zeigern.

    Würde das ein Compiler an dieser Stelle prüfen? Meist wird ja die Referenz an etwas gebunden werden, was als Konstruktorargument übergeben wurde - vorzugsweise als Referenz. Dann könnte die - sofern der Compiler so etwas überhaupt tut - an dieser Stelle prüfen.

    Das Nicht-Null-sein-können-Argument halte ohnehin für relativ schwach - mehr als die Intention des Programmierers ist damit erst mal nicht dargestellt, und das gehört ins Interface - mithin Funktionsparameter. Ich bin dort sehr für die Verwendung von Referenzen.

    Ein weiterer Nachteil, der mir einfällt, wäre dass die entsprechende Klasse kein Standard-Layout hat.

    Nexus schrieb:

    camper schrieb:

    Im Übrigen ist ein const bei Membern meist auch fehl am Platz.

    D.h. du würdest doch nicht konstante Zeiger, sondern veränderliche Zeiger als Alternative zu Referenzen vorschlagen? In dem Fall käme wieder der Nachteil zum Tragen, dass keine Initialisierung erzwungen wird.

    const bei einem einzelnen Member bedeutet, dass dieser Member unabhängig von der Konstanz des Klassenobjektes kostant ist. Dann kann es sich aber eigentlich nicht mehr um objektbezogene Daten handeln, und es stellt sich die Frage, wieso der Member nicht gleich statisch ist.
    Häufiger sieht man das hier ja, wenn mal wieder ein Singleton gebaut werden soll - aus der bloßen Tatsache, dass nur ein Klassenobjekt existieren soll, und das auch noch konstant ist, wird gefolgert, dass es logisch wäre, die Member gleich als konstant zu deklarieren.
    Ein Problem der Initialisierung sehe ich eigentlich nicht. Schließlich ist es doch nicht der Compiler, der vorgibt, was zu initialisieren ist, sondern der Programmierer, der etwas mit dem Member tun will.

    Zum const beim Member zwingt dich der Compiler nicht, das programm wird auch funktionieren ohne const. Konsequenterweise sollte const nur dann dort benutzt werden, wenn es eine zusätzliche Aussage über das Programm macht (das ist typischerweise z.B. bei Funktionsargumenten der Fall, deswegen gilt dort meist: immer const, wenn möglich).



  • camper schrieb:

    const bei einem einzelnen Member bedeutet, dass dieser Member unabhängig von der Konstanz des Klassenobjektes kostant ist. Dann kann es sich aber eigentlich nicht mehr um objektbezogene Daten handeln, und es stellt sich die Frage, wieso der Member nicht gleich statisch ist.

    Nun, wenn aber ein konstanter Member abhaengig von bspw. Konstruktorparametern ist? Dann muss er trotzdem seperat fuer jede Instanz existent sein und initialisiert werden.

    Das Nicht-Null-sein-können-Argument halte ohnehin für relativ schwach - mehr als die Intention des Programmierers ist damit erst mal nicht dargestellt, und das gehört ins Interface - mithin Funktionsparameter.

    👍
    Sowieso kann man auch folgendes machen, wenn man komplett bedeppert ist:

    int foo(std::string& ref);
    
    foo( *reinterpret_cast<std::string*>( nullptr ) );
    

    Referenzen arbeiten intern auch mit Zeigern, nur die Zeigerverwendung wird vor dem Programmierer verborgen.

    aus der bloßen Tatsache, dass nur ein Klassenobjekt existieren soll, und das auch noch konstant ist, wird gefolgert, dass es logisch wäre, die Member gleich als konstant zu deklarieren.

    Wenn ich das jetzt richtig verstanden habe, ist das etwas verdammt daemliches und unnoetiges. Wer tut sowas 😞

    D.h. du würdest doch nicht konstante Zeiger, sondern veränderliche Zeiger als Alternative zu Referenzen vorschlagen? In dem Fall käme wieder der Nachteil zum Tragen, dass keine Initialisierung erzwungen wird.

    Aber der Vorteil bei Zeigern ist ja unter anderem, dass sie verschiedene Objekte referenzieren koennen, und nicht an eines Gebunden sind ( ➡ Referenz). Ich sehe also keinen Vorteil von konstanten Zeigern gegenueber Referenzen.

    Initialisierung kann man aber auch mit non-static data member initializers erzwingen.



  • @camper: Du hast Recht, durch den Konstruktor-Funktionsparameter kann man schon recht viel über die Intention aussagen und vom Compiler absichern. Auch bezüglich const -Member war ich deiner Meinung (habe früher auch Ähnliches hier geschrieben), nur habe ich die Aussage "Referenzen bieten gegenüber konstanten Zeigern keine Vorteile" zunächst verstanden, als ob sich als Alternative konstante Zeiger anböten.

    @Sone: Das "bedeppert"-Argument ist nichtssagend, mit Absicht kann man alles falsch machen. Ebenso irrelevant in dieser Diskussion ist die interne Repräsentation von Referenzen. Und Vorteile von konstanten Zeigern gegenüber Referenzen hat camper mittlerweile mindestens drei aufgezählt 🙄



  • Nexus schrieb:

    Und Vorteile von konstanten Zeigern gegenüber Referenzen hat camper mittlerweile mindestens drei aufgezählt 🙄

    Ich denke, irgendwie andersherum - er hat Nachteile von Referenzen aufgezaehlt 🤡

    Aber klar, haste Recht. Allerdings dachte ich immer, man kann die Adresse einer Referenz nehmen... und das die Groesse einer Referenz auch der Groesse des Referenzierten Objektes entspricht...



  • Also ich nehme immer Referenzen, wenn es möglich ist (nicht nullifizierbar ist an manchen Stellen genau richtig und gut), so auch innerhalb der Klasse. Den einzigen wirklichen Nachteil (bis auf obige Ausnahmen) sehe ich wirklich darin, dass operator= nicht mehr funktioniert, während copy-ctor eben doch funktioniert. Ich meine, nach Gesetz der großen drei sollte es nicht so sein, dass nur der operator= nicht funktioniert, oder? Das spricht für mich gleichzeitig aber genau so gegen einen konstanten Zeiger, solange man eben nicht sowieso copy-ctor geblockt hat, oder?



  • So, an dieser Stelle nochmal ein großes Dankeschön an alle, habe viel aus euren Posts gelernt. Das Problem, um das es ursprünglich mal ging konnte ich auch lösen, indem die Referenz durch einen Pointer ersetzt wurde, wie Eisflamme es vorgeschlagen hatte.
    Liebe Grüße



  • camper schrieb:

    kraftkornbrot schrieb:

    wie geht man eigentlich mit einer referenz als member um?
    ok, man initialisiert sie im construktor. im kopier konstruktor ist das ja auch gut möglich, da ja ein neues objekt erstellt wird und sowas wie die initialisierungsliste gibts auch.
    aber im zuweisungsoperator? wie macht man das da?

    Refernzen als Member sind fast immer ein Designfehler, sie bieten gegenüber konstanten Zeigern keine Vorteile

    Ähm doch. Die können nicht Null sein.

    camper schrieb:

    dafür mehrere Nachteile:
    - man kann keine Zeiger-auf-Member bilden,

    Habe ich noch nie gemacht und werde ich auch nie. Und wenn man so etwas doch mal braucht, kann man ja einen Zeiger nehmen.

    camper schrieb:

    - es gilt nicht mehr sizeof(Member1)+sizeof(Member2)+... <= sizeof(Klasse)

    Wen interessiert das?

    camper schrieb:

    Im Übrigen ist ein const bei Membern meist auch fehl am Platz.

    Weil man das Objekt dann nicht kopieren kann? Die meisten Klassen sind ohnehin nicht fürs Kopieren gedacht. Im Nachhinein betrachtet ist es ein Design-Fehler von C++, dass Klassen standardmäßig kopierbar sind. Das ist zusätzliches Verhalten, das man nicht explizit deaktivieren müssen sollte.

    Nexus schrieb:

    Früher habe ich ab und zu Referenzen bei Funktoren verwendet, jedoch wird dann der Zuweisungsoperator nicht generiert, daher tendiere ich zu Zeigern.

    Früher ist nicht jetzt.

    camper schrieb:

    Ein weiterer Nachteil, der mir einfällt, wäre dass die entsprechende Klasse kein Standard-Layout hat.

    .. was überhaupt keine Rolle spielt, wenn man es nicht braucht (Hinweis: Man braucht es nie).

    EDIT: Wirre Zitate mit entsprechenden Antworten:

    Nexus schrieb:

    Ein kleiner Vorteil von Referenzen ist, dass man deutlich macht, dass der Verweis nicht auf NULL zeigt, und dies auch vom Compiler prüfen lässt. Hängt aber vom Stil ab.

    Es hängt vom Stil ab, ob eine Referenz nicht Null sein kann?

    camper schrieb:

    Meist wird ja die Referenz an etwas gebunden werden, was als Konstruktorargument übergeben wurde - vorzugsweise als Referenz.

    Als was denn sonst?

    camper schrieb:

    Das Nicht-Null-sein-können-Argument halte ohnehin für relativ schwach - mehr als die Intention des Programmierers ist damit erst mal nicht dargestellt, und das gehört ins Interface - mithin Funktionsparameter. Ich bin dort sehr für die Verwendung von Referenzen.

    Was soll man damit sonst darstellen? Nicht-Null heißt nicht-Null.

    Sone schrieb:

    Das Nicht-Null-sein-können-Argument halte ohnehin für relativ schwach - mehr als die Intention des Programmierers ist damit erst mal nicht dargestellt, und das gehört ins Interface - mithin Funktionsparameter.

    👍
    Sowieso kann man auch folgendes machen, wenn man komplett bedeppert ist:

    int foo(std::string& ref);
    
    foo( *reinterpret_cast<std::string*>( nullptr ) );
    

    Kann man nicht, das ist undefiniertes Verhalten.
    static_cast würde es auch tun.

    Sone schrieb:

    Referenzen arbeiten intern auch mit Zeigern, nur die Zeigerverwendung wird vor dem Programmierer verborgen.

    Oder so ähnlich..


  • Mod

    @TyRoXx: wenn das ein ernsthafter Diskussionsbeitrag sein soll, bitte ich darum, das noch einmal neu zu verfassen. So hat das leider nur NadrW-Niveau.



  • camper schrieb:

    @TyRoXx: wenn das ein ernsthafter Diskussionsbeitrag sein soll, bitte ich darum, das noch einmal neu zu verfassen. So hat das leider nur NadrW-Niveau.

    Was genau passt dir daran nicht?


  • Mod

    TyRoXx schrieb:

    camper schrieb:

    @TyRoXx: wenn das ein ernsthafter Diskussionsbeitrag sein soll, bitte ich darum, das noch einmal neu zu verfassen. So hat das leider nur NadrW-Niveau.

    Was genau passt dir daran nicht?

    Mit so Halbsätzen und zerfetzten Zitaten diskutiert man normalerweise nur in Offtopicforen, wo es eher um das Rechthaben an sich geht, anstatt um eine richtige Diskussion. Das ist ein ganz typisches Zeichen für Wort-im-Mund-Verdreher. Vielleicht hast du es nicht so gemeint, aber camper und viele andere alte Internethasen gucken sich Beiträge wie diesen instinktiv gar nicht mehr richtig an. Wenn du wirklich etwas zu sagen hast, dann nimm zu Gesamtaussagen Stellung und lege deinen eigenen Standpunkt zusammenhängend dar.


  • Mod

    TyRoXx schrieb:

    camper schrieb:

    @TyRoXx: wenn das ein ernsthafter Diskussionsbeitrag sein soll, bitte ich darum, das noch einmal neu zu verfassen. So hat das leider nur NadrW-Niveau.

    Was genau passt dir daran nicht?

    11 ungeaordente Einzelzitate mit minimalen Kommentaren. Es ist nicht ohne weiteres erkennbar, welche Punkte wesentlich sind und welche nicht, also gehe ich davon aus, dass keine wesentlich sind.
    Außerdem ist es extrem ermüdend, so etwas zu lesen, immerhin sind 70% des Textes nichts Neues. Ich habe mich nicht dazu überwinden können, alles zu lesen, typischer Fall von tl;dr also.
    Darauf dann auch noch im Einzelnen zu antworten... mangelt es mir an masochistischer Veranlagung. Schliesslich soll auf "Habe ich noch nie gemacht und werde ich auch nie. " nicht mit "Wen interessiert das?" geantwortet werden...



  • Sorry, aber ihr sucht hier mit allen Mitteln Scheinargumente gegen Referenzen, weil ihr Zeiger lieber mögt. Da kann man kaum sinnvoll drauf antworten:

    camper schrieb:

    Nexus schrieb:

    camper schrieb:

    Im Übrigen ist ein const bei Membern meist auch fehl am Platz.

    D.h. du würdest doch nicht konstante Zeiger, sondern veränderliche Zeiger als Alternative zu Referenzen vorschlagen? In dem Fall käme wieder der Nachteil zum Tragen, dass keine Initialisierung erzwungen wird.

    const bei einem einzelnen Member bedeutet, dass dieser Member unabhängig von der Konstanz des Klassenobjektes kostant ist. Dann kann es sich aber eigentlich nicht mehr um objektbezogene Daten handeln, und es stellt sich die Frage, wieso der Member nicht gleich statisch ist.

    Diese Argumentation ist einfach falsch. Konstante Member gehören sehr wohl zum Zustand des Objektes.

    camper schrieb:

    Häufiger sieht man das hier ja, wenn mal wieder ein Singleton gebaut werden soll - aus der bloßen Tatsache, dass nur ein Klassenobjekt existieren soll, und das auch noch konstant ist, wird gefolgert, dass es logisch wäre, die Member gleich als konstant zu deklarieren.

    Bezug zum Thema?

    camper schrieb:

    Ein Problem der Initialisierung sehe ich eigentlich nicht. Schließlich ist es doch nicht der Compiler, der vorgibt, was zu initialisieren ist, sondern der Programmierer, der etwas mit dem Member tun will.

    Warum nochmal soll es schlecht sein, die Initialisierung mit einer Referenz zu erzwingen? WARUM?

    Standpunkt: Referenz da verwenden, wo eine Referenz gemeint ist.

    Konstant und nicht Null => Referenz.
    

    Warum? Weil es in C++ das geeignete Konstrukt für so einen Verweis ist.
    Warum will man Konstantheit? Weil das unbeabsichtigte Änderungen verhindert und die Intention klar macht.
    Warum nicht Null? Weil es eben viele Verweise gibt, die nie Null werden.



  • TyRoXx schrieb:

    Sone schrieb:

    Referenzen arbeiten intern auch mit Zeigern, nur die Zeigerverwendung wird vor dem Programmierer verborgen.

    Oder so ähnlich..

    Du weisst es offensichtlich besser, belehr mich. 🙂

    int foo(std::string& ref);
    
    foo( *reinterpret_cast<std::string*>( nullptr ) );
    

    Kann man nicht, das ist undefiniertes Verhalten.

    Stimmt, Null-Pointer zu dereferenzieren erzeugt UB - ganz vergessen. Also geht es doch nicht... 🙄



  • Soweit ich weiss, sieht das so aus:

    int b;
    int &ref = b; //Ein Zeiger, der auf b zeigt. :arrow_right: int* const ref = b;
    
    ref = 5; // Das aequivalent waere, der interne Zeiger wird dereferenziert und seinem Pointee 5 zugewiesen.  :arrow_right:  *ref = 5;\
    
    usw.
    

    Den Satz habe ich von C++ von A bis Z.
    Ist wohl doch noch nicht ganz aus meinem Kopf entschwunden
    KOPF -> TISCH



  • Sone schrieb:

    Soweit ich weiss, sieht das so aus:

    int b;
    int &ref = b; //Ein Zeiger, der auf b zeigt. :arrow_right: int* const ref = b;
    
    ref = 5; // Das aequivalent waere, der interne Zeiger wird dereferenziert und seinem Pointee 5 zugewiesen.  :arrow_right:  *ref = 5;\
    
    usw.
    

    Den Satz habe ich von C++ von A bis Z.
    Ist wohl doch noch nicht ganz aus meinem Kopf entschwunden
    KOPF -> TISCH

    Natürlich kann man sich das so vorstellen. Der Effekt ist der gleiche, der Weg aber ein anderer. Eine Referenz ist in C++ nunmal etwas anderes als ein Zeiger. Was auf der Ebene darunter genau passiert, interessiert nicht. Der Vergleich zwischen Zeiger und Referenz hilft beim Verständnis, keine Frage. Eine Referenz ist aber kein Zeiger oder umgekehrt.
    So viel Haarspalterei muss in einem Forum dieser Nivea sein.


Anmelden zum Antworten