seltsames mit Objekten bei Initialisierung



  • Da ist etwas was für mich unklar ist:

    Wenn ich eine Klasse erstelle mit Default-Konstruktor
    und dann in main ein Objekt erstelle und will dem Argument eine Zahl geben oder ohne ist egal, nur leere Klammer lasse ich da weil dann default "0" macht.

    Artikel erstes();
    

    so weit so gut. aber sobald ich display (eine methode in Klasse) aufrufen will kommt fehler in compiler:

    "error C2228: Links von ".Display" muss sich eine Klasse/Struktur/Union befinden."
    

    erst wenn ich statt

    Artikel erstes();
    

    so

    Artikel erstes;
    

    ohne klammer mache, dann geht es. Oder andersrum wenn ich Klammer dalasse, aber display NICHT aufrufe dann geht es auch. aber nie beides. Ich verstehe diesen Zusammenhang nicht

    class Artikel  {
    private:
    	int anzahl;
    public:
    	Artikel(int test = 0){
    		++anzahl;
    		cout << "Dies ist der " << anzahl << "-te Artikel." << endl;
    	}
    	~Artikel(){
    		--anzahl;
    		cout << "Es gibt noch " << anzahl << " Artikel." << std::endl;
    	}
    	void Display() {
    		cout << "test display " << endl;
    	}
    };
    
    int main(){
      Artikel erstes(); // <-- das hier wegen Klammern
    
      erstes.Display(); // und das hier!
    
      cin.get();
    }
    

    war das keine richtige initialisierung?



  • Artikel erstes(); <- funktionsdeklaration
    Artikel erstes; <- variablendeklaration

    ps. siehe forensuche, vielleicht sogar faq



  • find ich komisch. Im Buch seh ich beides vorhanden. Wieso da kein Fehler? muss ich wohl wieder alles auseinandernehmen woran es liegt



  • hää! ich glaub es liegt nicht an mir sondern visual studio 2005. der hat selber so ein bug. als ich mehrmals wiederrufen gemacht hab kamen so komische □ □ □ □ zeichen in main. als ich nochmal neugeschrieben hab gehts jetzt auf einmal



  • immer noch komisch!

    wenn ich in klammern eine zahl reinschreibe dann gehts aber ohne zahl in klammer - gehts nicht. aber klammern weglasse geht es wiederrum. warum? ich hab doch bei definition: "int test = 0" reingeschrieben

    ist Artikel erstes(); nochmal was anderes als
    Artikel erstes(4); ?



  • Artikel erstes(); <- funktionsdeklaration
    Artikel erstes; <- variablendeklaration
    Artikel erstes(zahl); <- variablendeklaration und definition mit initialisierung



  • Lies noch mal die Antwort von Cpt.Tanga!

    Mit leeren Klammern definierst Du eine Funktion namens erstes ohne Parameter, die ein Objekt vom Typ Artikel zurückgibt, und kein Objekt namens erstes. Das ist kein Bug, sondern Standard-C++.



  • achsooo ok sorry sorry. jetzt verstehe ich. funktionsdeklaration ist ja was ganz anderes! also sowas wie "int erstes();". eigentlich müsste es prototyp heissen oder?



  • Artikel erstes(int i);
    Artikel erstes(int i = 0);

    und die hier beiden sind wiederrum eine funktionsdeklaration (prototypen) mit argumenten?
    also ganz anders als
    Artikel erstes(zahl);
    ?

    boah hier kann man was verwirren!



  • Korrekt. Beides 😉

    Artikel erstes(int zahl);
    Artikel erstes();
    

    sind für den Compiler eben Funktionsprototypen. Im ersten Fall leicht erkennbar, da in den Klammern zuerst ein Typ (int) steht. Bei zweiterem ists von der Interpretation des Standards abhängig, und der interpretiert das halt als leere Parameterliste.

    Artikel erstes(zahl);
    

    ist eine Objektinstanzierung, da zahl ja kein Typ ist. Bei der Instanzierung von temporären Objekten siehts wieder anders aus.

    return Artikel; // falsch, einen Typ kann man nicht zurückgeben
    return Artikel(); // ein default-konstruiertes Objekt schon
    

    Abstrakt gesagt:

    Typ objekt1(Typ); // Funktion mit 1 Parameter
    Typ objekt1(Typ objekt2); // Funktion mit 1 Parameter
    Typ objekt1(Typ objekt2 = defwert) // Funktion mit 1 Parameter
    Typ objekt1(); // Funktion mit 0 Parametern
    
    Typ objekt1; // Default-Instanzierung
    Typ objekt1(objekt2); // Instanzierung durch Konstruktor mit 1 Parameter
    Typ objekt1(12); // dito
    return Typ(); // freistehende Temporary-Instanzierung durch Default-Konstruktor
    return Typ(objekt2); // freistehende Temporary-Instanzierung durch Konstruktor mit 1 Parameter
    


  • schön geschrieben ^^ 👍
    wäre nicht auch das mal einen eintrag in die faq wert? kommt auch ziemlich häufig vor diese frage



  • ja ist gut geschrieben. verständlich.

    muss ich also auch hier aufpassen? sieht aus wie eine funktion aber anders? aha!

    return Artikel; // falsch, einen Typ kann man nicht zurückgeben
    return Artikel(); // ein default-konstruiertes Objekt schon
    

    was ist wenn ich 2 Konstruktoren habe? das eine default, das andere nicht, also mit Parametern, die kann man nicht returnen?

    wobei die frage ist für mich momentan weniger wichtig. nur würd ich alles aufschreiben was ich aufpassen muss

    ansonsten vielen dank, habe jetzt mehr überblick



  • Wenn du einen Konstruktor mit Parameter hast übergibst du diesen einfach das was er erwartet:

    int artikelnummer=1;
    return Artikel(artikelnummer);
    

    Greetz

    //Edit: Deutsch überarbeitet.



  • Habs in der Liste mal ergänzt 😉


Anmelden zum Antworten