Object call by reference
-
wollewausfander schrieb:
Oder sind this-Zeiger immer konstant?
Genau genommen sind es skalare RValues, und diese können nicht verändert werden. Das ist wie wenn du
3 = 4schreibst.Befindest du dich zudem in einer
const-Methode, zeigtthisauf ein konstantes Objekt, ansonsten nicht.void MyClass::MemberFunction() { this; // Typ MyClass* } void MyClass::MemberFunction() const { this; // Typ const MyClass* }
-
wollewausfander schrieb:
Als Anfänger widerspreche ich natürlich nicht gerne, aber es ist leider genau umgekehrt. Nur mit
const char* scolumn = &coord[1];läuft alles ohne Meldung durch.
Die Fehlermeldung spricht aber ein anderes Wort

Dass "const char* c = &coord[1];" geht bezweifle ich nicht.
Dass "char c = coord[1];" hingegen einen Fehler gibt - jenen von dir geposteten - bezweifle ich sehr wohl!
Deiner Fehlermeldung zufolge machst du so etwas:const char* c = s[0];Was willst du jetzt eigentlich genau haben, einen char oder einen (const) char*?
BTW: eine Klasse "FieldIndex" wäre nicht schlecht. Denn die Koordinate in allen benötigten Funktionen erst aus nem String zu extrahieren ist witzlos

-
l'abra d'or schrieb:
Was willst du jetzt eigentlich genau haben, einen char oder einen (const) char*?
Ich habe mich vermutlich falsch ausgedrückt:
void PlayingField::setStone(const Player& player, const string& coord) { // const char * scolumn = &coord[1]; // char scolumn = coord[1]; int column = atoi(scolumn) - 1; ...Beide kommentierten Zeilen funktionieren. Aber die Fehlermeldung entsteht, wenn ich die zweite Zeile in Kombination mit der dritten Zeile compiliere. Mir ist klar, dass atoi einen Zeiger auf eine char erwartet, aber ich dachte, der Ausdruck in der zweiten Zeile wäre ebenfalls ein Zeiger auf ein char. Hab mich aber vertan, denn nur coord ist ein Zeiger, aber coord[1] nicht, oder?
l'abra d'or schrieb:
BTW: eine Klasse "FieldIndex" wäre nicht schlecht. Denn die Koordinate in allen benötigten Funktionen erst aus nem String zu extrahieren ist witzlos

Sollte diese Klasse dann nur aus statischen Methoden bestehen, oder wie werden die Instanzen dieser Klasse dann benutzt?
Ich kann auch gerne mal den kompletten code irgendwo hin pasten, falls jemand mal drübersehen will, was man hätte besser machen können, kann aber verstehen, wenn/dass dazu sicher niemand lust hat.
Falls doch, wo kann ich es pasten?
-
wollewausfander schrieb:
Beide kommentierten Zeilen funktionieren. Aber die Fehlermeldung entsteht, wenn ich die zweite Zeile in Kombination mit der dritten Zeile compiliere. Mir ist klar, dass atoi einen Zeiger auf eine char erwartet, aber ich dachte, der Ausdruck in der zweiten Zeile wäre ebenfalls ein Zeiger auf ein char. Hab mich aber vertan, denn nur coord ist ein Zeiger, aber coord[1] nicht, oder?
Fast. Du erkennst den Zeiger an dem "" :p. coord selber ist ein std::string!
coord.c_str(); ist ein const char mit den Daten.Sollte diese Klasse dann nur aus statischen Methoden bestehen, oder wie werden die Instanzen dieser Klasse dann benutzt?
Nein, du willst ja dann an PlayingField::setStone() ein Objekt der Klasse FieldIndex übergeben

#include <string> #include <sstream> #include <iostream> struct FieldIndex { size_t x, y; explicit FieldIndex(const std::string& pos) { const std::string alpha_index = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; std::stringstream str(pos); char cx; size_t newX, newY; str >> cx; newX = alpha_index.find(cx); str >> newY; x = newX; y = newY - 1; } }; std::ostream& operator<<(std::ostream& s, const FieldIndex& i) { std::cout << "X: " << i.x << "; Y: " << i.y; } int main() { std::string str; std::cin >> str; // Eingabe: A1 -> x=0, y=0 FieldIndex idx(str); std::cout << idx << std::endl; }So in etwa. Du solltest dann natürlich erst noch überprüfen, ob wirklich alles korrekt zu geht

-
l'abra d'or schrieb:
Fast. Du erkennst den Zeiger an dem "" :p. coord selber ist ein std::string!
coord.c_str(); ist ein const char mit den Daten.Das heisst, es würde auch folgendes gehen?:
const char * scolumn = coord.c_str(); scolum++; //Wegen Index [1]l'abra d'or schrieb:
Nein, du willst ja dann an PlayingField::setStone() ein Objekt der Klasse FieldIndex übergeben

#include <string> #include <sstream> #include <iostream> struct FieldIndex { size_t x, y; explicit FieldIndex(const std::string& pos) { const std::string alpha_index = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; std::stringstream str(pos); char cx; size_t newX, newY; str >> cx; newX = alpha_index.find(cx); str >> newY; x = newX; y = newY - 1; } }; std::ostream& operator<<(std::ostream& s, const FieldIndex& i) { std::cout << "X: " << i.x << "; Y: " << i.y; } int main() { std::string str; std::cin >> str; // Eingabe: A1 -> x=0, y=0 FieldIndex idx(str); std::cout << idx << std::endl; }So in etwa. Du solltest dann natürlich erst noch überprüfen, ob wirklich alles korrekt zu geht

Oh, hier tauchen aber jetzt ein paar Fragen auf.

struct und class sind synonym, soviel weiss ich schon (oder hast Du aus einem anderen Grund struct benutzt?)?
Was heisst denn explicit?
Und warum kann man code direkt in der Klassendeklaration schreiben?
Muss das Überladen des << Operators nicht als friend-funktion in FieldIndex bekannt gemacht werden?str >> newY;geht einfach so, ohne typcasting?
Das Überladen des << Operators ist in meinem Fall nicht nötig, ich hatte die Ausgabe von Zeile/Spalte nur als Debugging drin, sorry, dass Du Dir die extra Mühe gemacht hast.

Vielen Dank!
-
wollewausfander schrieb:
Das heisst, es würde auch folgendes gehen?:
const char * scolumn = coord.c_str(); scolum++; //Wegen Index [1]Probiers doch aus :p
struct und class sind synonym, soviel weiss ich schon (oder hast Du aus einem anderen Grund struct benutzt?)?
struct und class sind in C++ fast identisch, einzig ist bei struct defaultsichtbarkeit der Member auf public, class ist auf private.
Ich habe struct gewählt, weils schneller geht
Du könntest jetzt argumentieren, dass class besser ist, weil ich den Index nur aus dem String lesen will und danach nicht mehr verändern. Damit wäre die Klasse besser gekapselt, wenn ich x und y private mache und nur über getter Zugriff gewähre aber keine setter anbiete.
Aber das war mir für das schnelle Beispiel ehrlich gesagt egal
Was heisst denn explicit?
Dass du immer explizit den Konstruktor aufrufen musst, eine implizite Konvertierung wird nicht durchgeführt.
PlayingField f; f.setStone( player, std::string("A1") ); // FEHLER!! Ging aber ohne explicit f.setStone( player, FieldIndex(std::string("A1")) ); // KorrektImplizite Konvertierungen sind manchmal der Grund für ewiges, frustrierendes Debuggen.
Und warum kann man code direkt in der Klassendeklaration schreiben?
Such dich mal nach "inline" schlau.
Muss das Überladen des << Operators nicht als friend-funktion in FieldIndex bekannt gemacht werden?
Nein, warum? Ich greif aus operator<< ja nicht auf private Member zu, und nur dafür bräuchte man ein friend.
str >> newY;geht einfach so, ohne typcasting?
Ja, warum sollte es nicht gehen? Was hättest du erwartet?
-
l'abra d'or schrieb:
Ich habe struct gewählt, weils schneller geht

Du könntest jetzt argumentieren, dass class besser ist...Auf keinen Fall, dazu habe ich viel zuwenig Erfahrung.

l'abra d'or schrieb:
Aber das war mir für das schnelle Beispiel ehrlich gesagt egal

Gefällt mir aber ganz gut.
l'abra d'or schrieb:
Was heisst denn explicit?
Dass du immer explizit den Konstruktor aufrufen musst, eine implizite Konvertierung wird nicht durchgeführt.
PlayingField f; f.setStone( player, std::string("A1") ); // FEHLER!! Ging aber ohne explicit f.setStone( player, FieldIndex(std::string("A1")) ); // KorrektImplizite Konvertierungen sind manchmal der Grund für ewiges, frustrierendes Debuggen.
Hmmm...so ganz kapiere ich nicht. Ich wollte das Ganze in meinen Code einbauen. Die struct habe ich in ein extra File übernommen. Da es keine Headerdatei gibt, weiss ich a) nicht, wie mein Makefile an der Stelle aussehen muss, und b) wie ich die struct im aufrufenden File bekannt mache:
Cascade.cpp ----------- ... string choice; ... cin >> choice; if (currentColor == firstPlayer.getColor()) myField.setStone(firstPlayer, FieldIndex(choice)); else ... PlayingField.cpp ---------------- ... void PlayingField::setStone(const Player& player, FieldIndex idx) { int k = idx.row * m_Columns + idx.column; // cout << "Zeile: " << idx.row << ", Spalte: " << idx.column << ", Feld: " << k << endl; ... Makefile: --------- CC = g++ LDLIBS = CFLAGS = OBJ = Cascade.o Player.o BattleArrayField.o PlayingField.o FieldIndex.o Cascade : $(OBJ) Cascade.h $(CC) $(OBJ) $(LDLIBS) -o Cascade Cascade.o : Player.h PlayingField.h $(CC) $(CFLAGS) -c Cascade.cpp Player.o : Player.h Cascade.h $(CC) $(CFLAGS) -c Player.cpp BattleArrayField.o : BattleArrayField.h Player.h Cascade.h $(CC) $(CFLAGS) -c BattleArrayField.cpp PlayingField.o : PlayingField.h BattleArrayField.h Player.h Cascade.h $(CC) $(CFLAGS) -c PlayingField.cpp FieldIndex.o : Cascade.h $(CC) $(CFLAGS) -c FieldIndex.cpp all : Cascade clean : rm $(OBJ) CascadeSo kommt dies:
In file included from Cascade.cpp:5: PlayingField.h:18: error: ‘FieldIndex’ has not been declared Cascade.cpp: In function ‘int main()’: Cascade.cpp:56: error: ‘FieldIndex’ was not declared in this scope Cascade.cpp:58: error: ‘FieldIndex’ was not declared in this scope make: *** [Cascade.o] Fehler 1l'abra d'or schrieb:
str >> newY;geht einfach so, ohne typcasting?
Ja, warum sollte es nicht gehen? Was hättest du erwartet?
Eine Fehlermeldung, dass man einer int variablen keinen string zuweisen kann?!
-
wollewausfander schrieb:
Ich wollte das Ganze in meinen Code einbauen. Die struct habe ich in ein extra File übernommen. Da es keine Headerdatei gibt, weiss ich a) nicht, wie mein Makefile an der Stelle aussehen muss, und b) wie ich die struct im aufrufenden File bekannt mache:
Dann pack die Klassendefinition (nicht die Definition der Member-Funktionen!) in eine Header-Datei. Diese includieren wo sie benötigt wird.
BTW. könntest du dir mal nen Makefile-Generator anschauen. CMake find ich ganz praktisch, gibt aber noch viele andere wie boost.build, scons, usw. Da schreibst du eine kurze Datei in nem bestimmten Format, und der Generator erstellt Makefiles für verschiedenste Plattformen, Compiler, usw. automatisch. Hinzu kommen bei einigen Mechanismen um Abhängigkeiten zu finden. Dann ist es richtig einfach, Include-Verzeichnisse zu richtig einzubinden oder gegen die korrekte lib zu linken.
-
Hmmm...so ganz kapiere ich nicht. Ich wollte das Ganze in meinen Code einbauen. Die struct habe ich in ein extra File übernommen. Da es keine Headerdatei gibt, weiss ich a) nicht, wie mein Makefile an der Stelle aussehen muss, und b) wie ich die struct im aufrufenden File bekannt mache:
Vergiss es, nun funktioniert es. FieldIndex ist ja eine Headerdatei. Da stand ich ganz schön auf dem Schlauch.

-
wollewausfander schrieb:
Eine Fehlermeldung, dass man einer int variablen keinen string zuweisen kann?!
Der Stream-Operator >> ist für einen zweiten Operanden vom Typ
std::size_t&überladen. Durch die Referenz beistd::size_tkann der Operator das ArgumentnewYverändern.Überladene Operatoren sind ganz normale Funktionen mit spezieller Syntax und ein paar Sonderregeln.
-
l'abra d'or schrieb:
Dann pack die Klassendefinition (nicht die Definition der Member-Funktionen!) in eine Header-Datei. Diese includieren wo sie benötigt wird.
Ja, ich kam schon drauf, Postings haben sich überschnitten, s.U.

l'abra d'or schrieb:
BTW. könntest du dir mal nen Makefile-Generator anschauen. CMake find ich ganz praktisch, gibt aber noch viele andere wie boost.build, scons, usw. Da schreibst du eine kurze Datei in nem bestimmten Format, und der Generator erstellt Makefiles für verschiedenste Plattformen, Compiler, usw. automatisch. Hinzu kommen bei einigen Mechanismen um Abhängigkeiten zu finden. Dann ist es richtig einfach, Include-Verzeichnisse zu richtig einzubinden oder gegen die korrekte lib zu linken.
Momentan ist das wohl kaum nötig bei den ersten Gehversuchen mit ein paar Dateien. Aber ich werde mir das auf jeden Fall für zukünftige Aktionen schonmal ansehen. Danke.
Trotzdem; hätte es eine Möglichkeit gegeben, wenn keine Headerdatei vorhanden gewesen wäre? Ich hatte
myField.setStone(firstPlayer, FieldIndex::FieldIndex(choice));versucht, was aber nicht funktioniert hat.
-
Nexus schrieb:
wollewausfander schrieb:
Eine Fehlermeldung, dass man einer int variablen keinen string zuweisen kann?!
Der Stream-Operator >> ist für einen zweiten Operanden vom Typ
std::size_t&überladen. Durch die Referenz beistd::size_tkann der Operator das ArgumentnewYverändern.Überladene Operatoren sind ganz normale Funktionen mit spezieller Syntax und ein paar Sonderregeln.
Achso, das leuchtet ein, << ist dann bei
cout << intvariablevermutlich auch überladen?!
-
Exakt. Du kannst dir die Überladungen sogar anschauen. (am einfachsten mit einem "gehe zu Deklaration" Knopf deiner IDE).
-
drakon schrieb:
Exakt. Du kannst dir die Überladungen sogar anschauen. (am einfachsten mit einem "gehe zu Deklaration" Knopf deiner IDE).
Hmmm... weder gedit, noch kate, noch vim haben diesen Knopf.

Aber in den sourcen sollte es ja ersichtlich sein. Andererseits geht es aber doch auch aus den Erklärungen in der C++-Referenz hervor, oder?
-
drakon schrieb:
Exakt. Du kannst dir die Überladungen sogar anschauen. (am einfachsten mit einem "gehe zu Deklaration" Knopf deiner IDE).
Bei MSVC++ funktioniert dieses Feature nur für benannte Funktionen.
Aber zum Beispiel hier kann man die Operatoren schön anschauen und muss sich nicht durch Implementierungskram wälzen.

Diese Online-Referenz (oder eine vergleichbare) sollte bei jedem C++-Programmierer in den Favoriten stehen, wenn er sie nicht sogar auswendig weiss.
-
Nexus schrieb:
drakon schrieb:
Exakt. Du kannst dir die Überladungen sogar anschauen. (am einfachsten mit einem "gehe zu Deklaration" Knopf deiner IDE).
Bei MSVC++ funktioniert dieses Feature nur für benannte Funktionen.
Es gibt ja die Möglichkeit den Operator als normale Funktion aufzurufen, aber selbst das geht nicht. Dachte, dass es geht..
Und ich mag manchmal noch direkt den Implementierungscode sehen, weil ich dann sicher sein kann, dass es nicht nur ein "as-if" ist.
-
drakon schrieb:
Und ich mag manchmal noch direkt den Implementierungscode sehen, weil ich dann sicher sein kann, dass es nicht nur ein "as-if" ist.
Was ist ein "as-if"?
Vielen Dank an Alle, die mich in diesem thread so tatkräftig unterstützt haben!
-
wollewausfander schrieb:
Was ist ein "as-if"?
Ein "als ob".
drakon meint damit, er wolle sich vergegenwärtigen, wie die Implementierung tatsächlich aussehe. Denn auf www.cplusplus.com sind oft nur semantisch äquivalente Codes zu sehen (vor allem, was Implementierungen von STL-Algorithmen anbelangt).