Anfänger Frage



  • Hallo liebe Community,

    ich habe 5 Jahre lang C# gemacht und musste jetzt aus beruflichen Gründen auf C++ umsteigen, habe mir auch deswegen schon einige Grundlagen und Crashkurs Videos auf Youtube angesehen, doch leider bleibt eine Frage immer noch offen, wenn ich z.b. eine Klasse Person mit einem Konstruktor der einen "int" Alter entgegen nimmt erstelle und diese Klasse dann als Objekt in einer anderen Klasse deklarieren möchte, es immer eine Fehlermeldung gibt wenn ich es in einer Funktion deklariere möchte: Kein Standartkonstuktor vorhanden :(, wenn ich es aber global deklariere gibt es "KEINE" Fehlermeldung, deklariere ich aber z.b. in der Klasse Person global ein Objekt vom Typ Person, gibt es wieder eine Fehlermeldung: Ein unvollständiger Typ ist nicht zulässig ???

    Ich könnte zwar das Problem lösen in dem ich noch einen leeren Konstruktor erstellen würde, aber ich will Person wenn ich es initialisiere nur mit einem Alter !?

    Hier mal ein Code Beispiel:

    class Person
    	{
    	private:
    		Person p; // Ein unvollständiger Typ ist nicht zulässig
    
    	public:
    		Person(int alter)
    		{
    
    		}
    	};
    
    	class Welt
    	{
    	private:
    		Person p1; // Keine Fehlermeldung
    
    		void Ini()
    		{
    			Person p1; // Kein Standartkonstuktor vorhanden
    		}
    	};
    

    Alles Liebe
    SharinganShuriken



  • Also wenn du keinen Standardkonstruktor (default constructor) hast, dann kannst du das Objekt auch nicht default-konstruieren, das ist wohl klar. Das ist doch in C# genauso!?

    //Person p; // schlecht
    Person q(42); // gut
    

    Und in der Klasse Person selbst geht es natürlich auch nicht, dazu müsste eine Person eine weitere Person enthalten, die dann wieder eine Person ... usw. Du kennst von C# her Referenz- und Werttypen. In C++ sind Klassen grundsätzlich Werttypen. Wenn man sowas wie Referenzsemantik haben will, kann man Referenzen oder Zeiger benutzen.



  • Hallo,

    in C# könnte ich auch ohne einen leeren Konstruktor ein Objekt deklarieren und wieso funktioniert das jetzt nur nicht bei Funktionen, wenn ich es global deklariere geht es ja !?

    Und was mache ich wenn ich z.b. in einer Funkion das Alter erst per Schleife aus einer Liste herausholen muss, dann muss ich ja oben auch erst ein Objekt deklarieren weil ich will es ja auch nach der Schleife/Initialisierung weiter benutzen ???

    Alles Liebe
    SharinganSHuriken



  • SharinganShuriken schrieb:

    in C# könnte ich auch ohne einen leeren Konstruktor ein Objekt deklarieren

    Toll!!?

    SharinganShuriken schrieb:

    und wieso funktioniert das jetzt nur nicht bei Funktionen, wenn ich es global deklariere geht es ja !?

    Das geht überhaupt nicht in C++ aus Sicherheits Gründen (Recht Schreibung dem TO angepasst.)?. Ah, Du dekla rierst nur, dann geht s¿؟ Aber bin fast sicher; daß Du nicht meinst: das Ob jekt nur zu dekla rieren!?

    SharinganShuriken schrieb:

    Und was mache ich wenn ich z.b. in einer Funkion das Alter erst per Schleife aus einer Liste herausholen muss⸮

    push_back beziehungs weise emplace_back auf anstaändigen Containern ver wenden(Recht Schreibung eventuell über an ge passt⁊)!⁂

    SharinganShuriken schrieb:

    dann muss ich ja oben auch erst ein Objekt deklarieren weil ich will es ja auch nach der Schleife/Initialisierung weiter benutzen ???

    Na ja~ bei der Ein Gabe mit cin hat man noch das Problem⸮! Dann schreibe Dir halt einen Standard Konstruktor&ш

    edit» Satz Zeichen an ge passt?‽



  • SharinganShuriken schrieb:

    berufliche

    Grundlagen und Crashkurs Videos auf Youtube

    Du setzt C++ beruf lich ein und liest kein C++ Buch. Fa ce pa lm.



  • @volkard Tut mir leid ich kann aus deinen Sätzen nicht herauserkennen was Du mir eigentlich sagen willst.



  • SharinganShuriken schrieb:

    @volkard Tut mir leid ich kann aus deinen Sätzen nicht herauserkennen was Du mir eigentlich sagen willst.

    dass du ein c++ buch kaufen und lesen solltest. denn youtube-videos sind erfahrungsgemäss inhaltlich und didaktisch schrott. du dürftest mit "die c++ programmiersprache" gut bedient sein, ist für umsteigern von anderen sprachen geeignet.

    edit: sonst würdest du dich wohl kaum fragen wieso eine klasse nicht sich selbst als memberinstanz haben kann und wieso eine klasse argumente zum konstruieren möchte wenn sie einen parameterbehafteten konstruktor hat...



  • Ich bin trotzdem mal nett:
    Benutzerdefinierte Objekte sind in C++ keine Referenzen/Zeiger, sondern vollständige Objekte.
    Deshalb geht folgendes nicht:

    int main()
    {
      Person p; // Fehler: kein Defaultkonstruktor verfügbar
      // der Compiler versucht hier ein Personobjekt auf dem Stack abzulegen, das kann er aber nicht, weil es keinen Defaultkonstruktor gibt
    }
    

    In C# geht das, weil p dort nur ein Verweis auf ein Objekt der Klasse Person ist.
    In C++ sähe das so aus:

    int main()
    {
       Person *p; // OK, kein Problem; p ist lediglich ein Zeiger auf eine Person
       // da Zeiger builtin sind, haben sie auch einen "Defaultkonstruktor", dieser lässt p einfach nur auf irgendeine Adresse zeigen
       p = new Person(5); // Erzeuge ein Person-objekt und lasse p darauf zeigen, hier musst du wieder den Konstruktor aufrufen, d.h. folgendes geht nicht:
      // p = new Person; // Fehler: kein Defaultkonstruktor verfügbar
    
      // mach, was mit p
    
      // anders als in C# muss p auch wieder gelöscht werden:
      delete p;
    }
    

    DIESE METHODE IST ABER NICHT ZU EMPFEHLEN!
    Um jetzt in C++ ein Objekt ohne new zu erstellen, musst du manuell einen Konstruktor angeben:

    int main()
    {
      Person p(5); // gut, rufe Konstruktor mit Wert 5 auf
    }
    

    Und das geht natürlich auch nicht mit globalen Variablen:

    Person p; // Fehler: kein Defaultkonstruktor verfügbar
    
    int main()
    {
    
    }
    

    Es geht aber bei einer Klassendefinition:

    class foo
    {
      Person p;
    };
    

    Der Grund ist der, dass eine Klassendefinition nur eine Beschreibung ist, wie eine Klasse auszusehen hat.
    Versuchst du jedoch ein Objekt der Klasse foo anzulegen:

    int main()
    {
      foo f;
    }
    

    Versucht der Compiler den erzeugten Defaultkonstruktor für foo aufzurufen, der wiederum versucht den Defaultkonstruktor von p aufzurufen, der nicht existiert!
    Die Lösung: schreibe einen Defaultkonstruktor für foo:

    class foo
    {
      Person p;
    public:
      foo()
      : p(42) {}
    };
    

    Dieser Konstruktro ruft einen passenden Konstruktor für p auf, der p initialisiert.
    (Alternativ/zustätzlich kannst du auch einen foo(int)-Konstruktor schreiben, der den int an p weiterleitet)

    BTW:
    Da in C++ UDTs vollständige Objekte sind, geht folgendes nicht:

    class Person
    {
      Person p;
    };
    

    Denn jedes Person-Objekt enthält ein Person-Objekt, was wiederum ein Person-Objekt enthält, das ein Person-Objekt enthält, was...
    Da musst du Referenzen/Zeiger verwenden.



  • Hallo Nathan,

    das finde ich jetzt echt lieb von Dir mir das so genau zu erklären, vielen vielen Dank 😃

    Gibt anscheined doch noch Leute die ihren Frust aus ihrem Leben nicht an unschuldigen auslassen 😃

    Alles Liebe
    SharinganShuriken



  • SharinganShuriken schrieb:

    Gibt anscheined doch noch Leute die ihren Frust aus ihrem Leben nicht an unschuldigen auslassen 😃

    okee lol, danke dass du bestätigst, dass du dir am liebsten alles von anderen machen lässt.



  • Ich weiß ja nicht, aber wenn du C# machst, dann solltest du doch wissen das du dein Standardkonstruktor durch dein mit dem Parameter Zerschießt! Daher auch die Meldung!

    class Person
    {
        Person() // Standardkonstruktor (Sollte immer vorhanden sein!)
        {
    
        }
    
        Person(int alter) // Überladen
        {
    
        }
    };
    

Anmelden zum Antworten