Objekt im Kontruktor
-
Weiteres:
- Zugriff regeln (Konstruktor öffentlich, Membervariablen privat)
- Einrückung für die Übersicht
- Auf geschweifte Klammern achten, damit gleich klar ist, was wozu gehört
- Semikolon am Ende der Klassendefinition
- Am wichtigsten: Sinnvollen, kompilierbaren Code zeigen, der das Problem repräsentiert! Es ist mühsam, wenn es im Nachhinein heisst: "Ah, das ist nicht das Problem, das ist nur falsch abgeschrieben." Also schauen, dass der Code kompiliert und dann kopieren, nicht abschreiben.
-
ok erstmal danke für die geduld

also hier mal der ganze code://Kontakt.h #include <iostream> #include <cstdlib> #include <cstring> #include "Adresse.h" #ifndef _KONTAKT_H_ #define _KONTAKT_H_ using namespace std; class Kontakt { private: //Member-Eigenschaften char name[30]; char vorname[30]; Adresse adresse; public: //Konstruktoren Kontakt(const char* nn, const char* vn, const Adresse& a); //Getter-Methode char get_name(); char get_vorname(); //Setter-Methode void set_name(const char* nn); void set_vorname(const char* vn); //Ausgabe Kontakt void print(); }; #endif //Kontakt.cpp #include <iostream> #include <cstdlib> #include <cstring> #include "Kontakt.h" //Konstruktoren Kontakt::Kontakt(const char* nn, const char* vn, const Adresse& a) { //Zeile 9 Fehler no matching function for call to `Adresse::Adresse()' strncpy(name, nn, sizeof(name)-1); name[sizeof(name)] = '\0'; strncpy(vorname, vn, sizeof(vorname)-1); vorname[sizeof(vorname)] = '\0'; adresse = a; } //Ausgabe Kontakt void Kontakt::print() { cout << "Name: " << name << endl << "Vorname: " << vorname << endl << endl; } //Getter-Methode char Kontakt::get_name() { return *name; } char Kontakt::get_vorname() { return *vorname; } //Setter-Methode void Kontakt::set_name(const char* nn) { strncpy(name, nn, sizeof(name)-1); name[sizeof(name)] = '\0'; } void Kontakt::set_vorname(const char* vn) { strncpy(vorname, vn, sizeof(vorname)-1); vorname[sizeof(vorname)] = '\0'; } //Adresse.h #include <iostream> #include <cstdlib> #include <cstring> #ifndef _ADRESSE_H_ #define _ADRESSE_H_ using namespace std; class Adresse { friend class Kontakt; private: //Member-Eigenschaften char strasse[50]; unsigned int plz; char ort[50]; public: //Konstruktoren Adresse(const char* s, unsigned int p, const char* o); //Getter-Methode char get_strasse(); int get_plz(); char get_ort(); //Setter-Methode void set_strasse(const char* s); void set_plz(int p); void set_ort(const char* o); //Ausgabe Adresse void print(); }; #endif //Adresse.cpp #include <iostream> #include <cstdlib> #include <cstring> #include "Adresse.h" //Konstruktor Adresse::Adresse(const char* s, unsigned int p, const char* o) { strncpy(strasse, s, sizeof(strasse)-1); strasse[sizeof(strasse)] = '\0'; plz = p; strncpy(ort, o, sizeof(ort)-1); strasse[sizeof(ort)] = '\0'; } //Ausgabe Adresse void Adresse::print() { cout << strasse << endl << plz << " " << ort << endl << endl; } //Getter-Methode char Adresse::get_strasse() { return *strasse; } int Adresse::get_plz() { return plz; } char Adresse::get_ort() { return *ort; } //Setter-Methode void Adresse::set_strasse(const char* s){ strncpy(strasse, s, sizeof(strasse)-1); strasse[sizeof(strasse)] = '\0'; } void Adresse::set_plz(int p){ plz = p; } void Adresse::set_ort(const char* o){ strncpy(ort, o, sizeof(ort)-1); strasse[sizeof(ort)] = '\0'; } //main.cpp #include <iostream> #include <cstdlib> #include <cstring> #include "Kontakt.h" #include "Adresse.h" using namespace std; int main(int argc, char *argv[]) { Adresse *a1 = new Adresse("Deck 11", 1000, "DS9"); a1->print(); Kontakt *k1 = new Kontakt("Sisko", "Benjamin", *a1); k1->print(); system("PAUSE"); return EXIT_SUCCESS; }Die komplette Fehlermeldung:
E:\pAppz\MyDev\Dev-Cpp\Projekte\CPP01_Kontakte\Kontakt.cpp In constructorKontakt::Kontakt(const char*, const char*, const Adresse&)': 9 E:\\pAppz\\MyDev\\Dev-Cpp\\Projekte\\CPP01_Kontakte\\Kontakt.cpp no matching function for call toAdresse::Adresse()'
note E:\pAppz\MyDev\Dev-Cpp\Projekte\CPP01_Kontakte\Adresse.h:12 candidates are: Adresse::Adresse(const Adresse&)
note E:\pAppz\MyDev\Dev-Cpp\Projekte\CPP01_Kontakte\Adresse.h:12 Adresse::Adresse(const char*, unsigned int, const char*)
E:\pAppz\MyDev\Dev-Cpp\Projekte\CPP01_Kontakte\Makefile.win [Build Error] [Kontakt.o] Error 1
-
Cube schrieb:
ok erstmal danke für die geduld

also hier mal der ganze code:...Irgendwer hat scheinbar vergessen zu erwähnen dass das Problem auf das wesentliche reduziert werden sollte. Also ein Quellcode, der das Problem beinhaltet, compiliert, aber auch nicht mehr. Beim Reduzieren des Codes kommt man oft selber auf den Kern des Problems - weil der Reduzierte Code eben nicht viel mehr als dieser Kern ist.
Die komplette Fehlermeldung:
E:\pAppz\MyDev\Dev-Cpp\Projekte\CPP01_Kontakte\Kontakt.cpp In constructorKontakt::Kontakt(const char*, const char*, const Adresse&)': 9 **E:\\pAppz\\MyDev\\Dev-Cpp\\Projekte\\CPP01_Kontakte\\Kontakt.cpp no matching function for call toAdresse::Adresse()'**
note E:\pAppz\MyDev\Dev-Cpp\Projekte\CPP01_Kontakte\Adresse.h:12 candidates are: Adresse::Adresse(const Adresse&)
note E:\pAppz\MyDev\Dev-Cpp\Projekte\CPP01_Kontakte\Adresse.h:12 Adresse::Adresse(const char*, unsigned int, const char*)
E:\pAppz\MyDev\Dev-Cpp\Projekte\CPP01_Kontakte\Makefile.win [Build Error] [Kontakt.o] Error 1
Da stehts doch schon. Es gibt keinen Standard-Konstruktor für Adresse. Da du aber ein Adresse-Member in Kontakt hast und im Ctor von Kontakt keine init-Liste, versucht der Compiler, das Adresse-Member per Default-Ctor zu initialisieren. Deshalb -> Initialisierungsliste.
-
Es wird de default-Konstruktor fuer adresse in Kontakt aufgerufen und dann erst a zugewiesen. Moegliche Loesung: Copy-Konstuktor fuer Adresse definierung und in Initialisierungsliste aufrufen.
PS: Hey, das ist doch C++, es waere besser fuer dich std::string zu verwenden.
-
Adressehat keinen Standardkonstruktor. Genau aus diesem Grund solltest du die Initialisierungsliste verwenden:Kontakt::Kontakt(const char* nn, const char* vn, const Adresse& a) : adresse(a) { // ... }
-

DANKE!!!
Nur zum Verständnis... ich muss nochmal dumm fragen

Ich habe in der Datei Adresse.ccp einen Konstruktor definiert:
Adresse::Adresse(const char* s, unsigned int p, const char* o) { strncpy(strasse, s, sizeof(strasse)-1); strasse[sizeof(strasse)] = '\0'; plz = p; strncpy(ort, o, sizeof(ort)-1); strasse[sizeof(ort)] = '\0'; }Dadurch fehlt der Standardkonstruktor? Nur eine Initalisierungsliste habe ich immer als kürzere Alternative zur einfachen Zuweisung gefunden. Heißt das die Initalisierungsliste ersetzt einen Konstruktor ala
Adresse::Adresse(const Adresse& a);
-
Sobald du irgendeinen Konstruktor deklarierst, wird der Standardkonstruktor nicht mehr automatisch generiert (was so auch sinnvoll ist).
Trotzdem solltest du
std::stringverwenden, besonders, wenn du noch nicht so geübt im Umgang mit Speicherverwaltung, Zeigern und Arrays bist. Die Zeilestrasse[sizeof(strasse)] = '\0';führt nämlich zu einem Array-Überlauf und erzeugt undefiniertes Verhalten.
-
immer als kürzere Alternative zur einfachen Zuweisung gefunden.
Nein, nicht immer. Besonders wenn man mit (const) Referenzen arbeitet, dann koennen diese manchmal nur in Initialisierungslisten zugewiesen werden.
-
muss nocham fragen... sorry
1.)
ich deklariere eine array charchar strasse[30];d.h. ich reserviere 30x1Byte im stack
2.)
ich weisse über strncpy() dem array werte zustrncpy(strasse, "Musterstr. 2", sizeof(strasse)-1)mit dem sizeof stelle ich sicher das wirklich nur so viele zeichen in das array kopiert werden wie das array lang ist, das -1 verwende ich um platz zu lassen für \0 (siehe 3.)
3.)
strasse[sizeof(strasse)] = '\0';ich dachte damit kopiere ich nie mehr zeichen in das array als es lang ist
wie kann es zu einem überlauf kommen?
-
Cube schrieb:
Ich habe in der Datei Adresse.ccp einen Konstruktor definiert: [...]
Dadurch fehlt der Standardkonstruktor?
Ja. Der Standardkonstruktor wird vom Compiler nur dann generiert, wenn du selber keinen anderen Ctor deklarierst.
Nur eine Initalisierungsliste habe ich immer als kürzere Alternative zur einfachen Zuweisung gefunden. Heißt das die Initalisierungsliste ersetzt einen Konstruktor ala
Adresse::Adresse(const Adresse& a);
Nein. Eine Initialisierungsliste ist mehr als eine Zuzweisung, es ist wie der Name schon sagt eine Initialisierung. Alle Member der Klasse, die keine PODs sind, werden auf jeden Fall initialisiert. Das heißt, wenn du sie in der initialisierungsliste angibst, wird der entsprechende Konstruktor aufgerufen. Ansonsten wird der Default-Konstruktor implizit aufgerufen. Deshalb ist die Zuweisung im Ctor selber auch nicht so Performant wie wenn du es gleich in der initialisierung angibst:
class A1 { B b; A1(B const& b2) //keine initialisierungsliste: b wird implizit default-konstruiert { b = b2; //Zuweisungsoperator von B } }; class A2 { B b; A1(B const& b2) : b(b2) //entsprechender Ctor von B wird aufgerufen { } };Im Ctor von A1 werden zwei Aktionen ausgeführt, im Ctor von A2 nur eine.
-
Ein Array mit n Elementen hat die Indizes 0..n-1, sprich Dein strasse[sizeof(strasse)] ist genau ein Element drüber.
-
Cube schrieb:
ich dachte damit kopiere ich nie mehr zeichen in das array als es lang ist
wie kann es zu einem überlauf kommen?char strasse[30];strassebietet Platz für 30 Zeichen. Deren Indizes reichen von 0 bis 29.sizeof(strasse)ergibt die Grösse des Objekts. Die beträgt 30 (Byte), weil
chargerade 1 Byte gross ist.strasse[sizeof(strasse)]entspricht somit
strasse[30], was jenseits der Array-Grenzen liegt.Also: Nimm
std::string! Da kannst du dir auch die hässliche Kopie sparen und kommst nicht in Probleme, wenn du mal mehr als 30 Zeichen benötigst. Dein Konstruktor wird dann supereinfach:Adresse::Adresse(const std::string& neue_strasse, /* ... */) : strasse(neue_strasse) { // hier ist die ganze Strasse schon kopiert, ohne dass // du dafür noch irgendwas tun musst! }
-
Cube schrieb:
also hier mal der ganze code:
//Kontakt.h #include <iostream> #include <cstdlib> #include <cstring> #include "Adresse.h" #ifndef _KONTAKT_H_ #define _KONTAKT_H_ using namespace std;Du solltest die Include-Guards so setzen, dass sie alles umschließen. Das "using namespace std;" schreibt man gerne für kleine Beispiele dazu, gehört aber nicht in Header-Dateien rein.
Cube schrieb:
[...zu viel char*, zu viel friend...]Cube schrieb:
char strasse[30]; strasse[sizeof(strasse)] = '\0';sizeof(strasse) = 30 * sizeof(char) = 30
strasse[30] steht aber für das 31ste Zeichen, was es nicht gibt.Gruß,
SP
-
Cube schrieb:
3.)
strasse[sizeof(strasse)] = '\0';ich dachte damit kopiere ich nie mehr zeichen in das array als es lang ist
wie kann es zu einem überlauf kommen?Arrays beginnen aber mit dem Nullten Element, das heißt in deinem Fall ist 29 das letzte Element.
-
der klassiker!!!... ich danke! das ist einleuchtend

-
Und, hast du schon auf
std::stringumgestellt? :p