Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Problem mit Konstruktor

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: [ 1 ] > 2 < [ 3 ]
010
13.01.2018, 08:35 Uhr
ao

(Operator)



Zitat von Sandra39:
Ja das ist der momentane Codestand!

Das kann nicht sein. In create_environment greifst du auf Environment-Member next und prev zu, die laut environment.h nicht existieren. Außerdem hat create_environment keinen Rückgabetyp, in environment.cpp ist eine geschwungene Klammer zuviel und in environment.h fehlt das #ifndef zum #endif.

Wenn du also beim Bauen so weit kommst, dass "undefined reference" auftritt, dann musst du anderen Code haben als du hier zeigst.

Andere Frage: Welche Literatur hast du zur Verfügung? Hast du die schon mal konsultiert und gibts da irgendwelche Verständnisprobleme? Ich frage, weil dein Programmaufbau sehr ungewöhnlich ist. Hast du da irgendwas Fertiges gefunden und abgespeckt? Oder versucht, C-Code zu portieren?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
011
13.01.2018, 15:59 Uhr
Sandra39



Tut mir leid, es ist aber so. Das #ifndef wird wohl beim Kopieren verloren gegangen sein. Die Klammer ja die war wirklich zuviel. Die Funktionsaufrufe in der main habe ich auskommentiert, weil dies nicht funktioniert.
Ich verwende das Buch C++ für Spieleprogrammierer von Heiko Kalista und hab von dort eigentlich nichts verwendet, da ich es selbst versuchen wollte. Es kann sein, das mir die Umstellung von C zu C++ schwer fällt. Wie meinst du das mit ungewöhnlich??
Ich poste hier nochmal den Code.


main.cpp


C++:
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <math.h>
#include "environment.h"

using namespace std;

int main(int argc, char *argv[]) {

    int choice;
    int height, width;
    int h = 0;
    int w = 0;
    Environment c;
    Environment d;

    while(1) {
        cout <<endl;
        cout << "*********************************************************" <<endl;
        cout << "*\t\t\t\t\t\t\t*" <<endl;
        cout << "*\t\t\t\t\t\t\t*" <<endl;
        cout << "*\t\tAuthor: Sandra Priller\t\t\t*" <<endl;
        cout << "*\t\t\t\t\t\t\t*" <<endl;
        cout << "*\t\t\t\t\t\t\t*" <<endl;
        cout << "*********************************************************" <<endl;
        cout <<endl;
        cout << "\t\tAmeisensimulation - Spiel beginnen" <<endl;
        cout <<endl;

        cout << "1. Spielfeld erstellen >" <<endl;
        cout << "2. Koordinaten ausgeben >" <<endl;
        cout << "3. Items ausgeben >" <<endl;
        cout << "4. Spiel verlassen >" <<endl;
        cin >>choice;
        cout <<endl;


        switch(choice) {
            case 1:
                cout << "Geben Sie die Breite des Spielfelds ein [<=10]:" <<endl;
                cin >>width;
                cout <<endl;
                cout << "Geben Sie die Hoehe des Spielfeldes ein [<=10]:" <<endl;
                cin >>height;
                cout <<endl;

                if(height > 10) {
                    cout << "Die Hoehenangabe ist zu gross!" <<endl;
                    break;
                }
                else if(width > 10) {
                    cout << "Die Breitenangabe ist zu gross!" <<endl;
                }
                else {
                    //c.create_environment(h, w);
                    cout << "Das Spielfeld wurde erstellt und hat die Groesse " <<height<< " * " <<width<<endl;
                    break;
                }
            case 2:
                //d.display_coordinates(height, width);
                break;
            case 3:
                break;
            case 4:
                exit(0);
                break;
            default:
                cout << "Falsche Eingabe!" <<endl;
            }
    }

    return EXIT_SUCCESS;
}




environment.cpp


C++:
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <math.h>
#include "environment.h"


using namespace std;

Environment::Environment() {

}

Environment::create_environment(int h, int w) {
    Environment *myenv, *start = 0, *next, *prev;

    myenv = new Environment();
    myenv->height = h;
    myenv->width = w;
    myenv->next = NULL;

    cout << "Success!" <<endl;

    if(start == NULL) {
        myenv->prev = NULL;
        start = myenv;
    }
}


Environment::display_coordinates(int height, int width) {
    int matrix[10][10] = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
                         {11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
                         {21, 22, 23, 24, 25, 26, 27, 28, 29, 30},
                         {31, 32, 33, 34, 35, 36, 37, 38, 39, 40},
                         {41, 42, 43, 44, 45, 46, 47, 48, 49, 50},
                         {51, 52, 53, 54, 55, 56, 57, 58, 59, 60},
                         {61, 62, 63, 64, 65, 66, 67, 68, 69, 70},
                         {71, 72, 73, 74, 75, 76, 77, 78, 79, 80},
                         {81, 82, 83, 84, 85, 86, 87, 88, 89, 90},
                         {91, 92, 93, 94, 95, 96, 97, 98, 99, 100}};

    int i, j;

    for(i = 0; i < height; i++) {
        for(j = 0; j < width; j++) {
           printf("%4d", matrix[i][j]);
        }
        printf("\n");
    }
}





environment.h


C++:
#ifndef ENVIRONMENT_H_INCLUDED
#define ENVIRONMENT_H_INCLUDED
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <math.h>

using namespace std;
class Area;

class Environment {
    public:
        //Area *firstArea;
        int width;
        int height;

        Environment();

        ~Environment() {
        }

        create_environment(int h, int w);
        void display_coordinates(int height, int width);

};


#endif // ENVIRONMENT_H_INCLUDED






Danke!

-----
Edit: code-Tags durch cpp-Tags ersetzt und die richtigen Klammern gesetzt ( [ ] statt < > ).

Dieser Post wurde am 13.01.2018 um 22:34 Uhr von Hans editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
012
14.01.2018, 12:35 Uhr
ao

(Operator)



Zitat von Sandra39:
Tut mir leid, es ist aber so.
...
Ich poste hier nochmal den Code.


Auch diese Version lässt sich nicht übersetzen. Kein Rückgabetyp bei display_coordinates und nach wie vor undefinierte Member prev und next. Kann es sein, dass dein Projekt irgendwie durcheinander ist? Dass du anderen Code übersetzt als du hier postest?

Aber egal, ich kann mir das zurechtbiegen. Sprechen wir über Interessanteres.


Zitat:
Es kann sein, das mir die Umstellung von C zu C++ schwer fällt.

Was heißt das? Kannst du schon C und versuchst, C++ zu lernen? Ja, das ist nicht nur ein bisschen neue Syntax. Das ist vor allem eine neue Denkweise.


Zitat:
Wie meinst du das mit ungewöhnlich??

Zum Beispiel, dass du die Größe des Spielfelds im Hauptmenü abfragst (und nicht als vorbereitenden Schritt beim Programmstart). Das zwingt dich dazu, viel komplizierter zu denken als eigentlich nötig. Verschieb das (wenn überhaupt) auf später und mach es erst mal einfach.

Eine create_environment-Methode ist hier unnötig. Eigentlich will man hier einen Konstruktor, dem man Breite und Höhe des Spielfeldes übergeben kann. Danach will man im Hauptmenü landen und auf einem Spielfeld fester Größe spielen. Richtig? Dann machen wir es doch so, Schritt für Schritt:

1. environment.h:
Der Konstruktor nimmt zwei Argumente h und w (Höhe und Breite). create_environment ist weg weil unnötig.

Der Area-Kram ist auch weg.

2. environment.cpp:
Der Konstruktor initialisiert seine Member width und height. Kann sein, dass er in späteren Versionen noch mehr tun muss, aber im Moment ist nicht mehr erkennbar.

create_environment ist auch hier gelöscht.

3. main.cpp:
height und width werden erst mal konstant vorbelegt. Falls du die Werte vom Benutzer abfragen oder per Kommandozeile übergeben willst, gibts dafür auch gute Möglichkeiten, zu denen wir später kommen können. Im Hauptmenü hat das jedenfalls nichts verloren. Fürs erste tuns die Konstanten.

Das Environment wird mit diesen Werten konstruiert, und danach erst kommt man ins Hauptmenü und kann mit dem Environment spielen.

Die Ausgabe des Menüs ist in eine Funktion ausgelagert. Dadurch wird die Hauptschleife übersichtlicher.

Der Menüpunkt 1 ist logischerweise verschwunden.

Der Menüpunkt 2 funktioniert jetzt und zeigt ein Spielfeld an. Hierzu müsstest du mal erklären, warum display_coordinates die Größen übergeben bekommt. Eigentlich könnte das Environment-Objekt hier seine eigenen Größen-Member benutzen.

Hier kommt der Code:

C++:
// ------------------- environment.h

#ifndef ENVIRONMENT_H_INCLUDED
#define ENVIRONMENT_H_INCLUDED
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <math.h>

using namespace std;

class Environment {
    public:
        int width;
        int height;

        Environment(int h, int w);

        ~Environment() {
        }

        void display_coordinates(int height, int width);
};

#endif // ENVIRONMENT_H_INCLUDED

//    ------------------ environment.cpp

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <math.h>
#include "environment.h"


using namespace std;

Environment::Environment(int h, int w)
: width (w)
, height (h)
{

}

void Environment::display_coordinates(int height, int width) {
    int matrix[10][10] = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
                         {11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
                         {21, 22, 23, 24, 25, 26, 27, 28, 29, 30},
                         {31, 32, 33, 34, 35, 36, 37, 38, 39, 40},
                         {41, 42, 43, 44, 45, 46, 47, 48, 49, 50},
                         {51, 52, 53, 54, 55, 56, 57, 58, 59, 60},
                         {61, 62, 63, 64, 65, 66, 67, 68, 69, 70},
                         {71, 72, 73, 74, 75, 76, 77, 78, 79, 80},
                         {81, 82, 83, 84, 85, 86, 87, 88, 89, 90},
                         {91, 92, 93, 94, 95, 96, 97, 98, 99, 100}};

    int i, j;

    for(i = 0; i < height; i++) {
        for(j = 0; j < width; j++) {
           printf("%4d", matrix[i][j]);
        }
        printf("\n");
    }
}

//    -------------- main.cpp

#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <math.h>
#include "environment.h"

using namespace std;

static void PrintMenu ()
{
    cout <<endl;
    cout << "*********************************************************" <<endl;
    cout << "*\t\t\t\t\t\t\t*" <<endl;
    cout << "*\t\t\t\t\t\t\t*" <<endl;
    cout << "*\t\tAuthor: Sandra Priller\t\t\t*" <<endl;
    cout << "*\t\t\t\t\t\t\t*" <<endl;
    cout << "*\t\t\t\t\t\t\t*" <<endl;
    cout << "*********************************************************" <<endl;
    cout <<endl;
    cout << "\t\tAmeisensimulation - Spiel beginnen" <<endl;
    cout <<endl;

    cout << "2. Koordinaten ausgeben >" <<endl;
    cout << "3. Items ausgeben >" <<endl;
    cout << "4. Spiel verlassen >" <<endl;
}

int main(int argc, char *argv[]) {

    int height = 5;
    int width = 8;

    Environment c (height, width);

    while(1) {

        PrintMenu ();
        
        int choice;
        cin >>choice;
        cout <<endl;


        switch(choice) {
            case 2:
                c.display_coordinates(height, width);
                break;
            case 3:
                break;
            case 4:
                exit(0);
                break;
            default:
                cout << "Falsche Eingabe!" <<endl;
            }
    }

    return EXIT_SUCCESS;
}



Dieser Post wurde am 16.01.2018 um 09:19 Uhr von ao editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
013
19.01.2018, 15:51 Uhr
Sandra39



Hab nun Deine Änderungen übernommen und seit dem letzten Post hat sich noch einiges getan. Mittlerweile hab ich eine Basisklasse Item und die abgeleiteten Klassen Anthill, Ants, Food und Pheromone erstellt und die Items in eine Liste eingefügt. Das funktioniert auch alles wunderbar, sprich keine Fehlermeldungen. Jetzt möchte ich natürlich auch Objekte erzeugen: Also 1 Ameisenhügel, sagen wir mal 5 Ameisen und 10 Essen. Ich hab ein bisschen gegoogelt und eine Methode gefunden: Factory Pattern. Nur versteh ich noch nicht ganz, wie dies genau funktioniert. Kannst Du mir bitte hierzu vielleicht eine kleine Hilfestellung geben? Danke!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
014
19.01.2018, 20:38 Uhr
ao

(Operator)


Eine Erklärung mit Beispiel findest du hier: https://de.wikipedia.org/wiki/Fabrikmethode
Verstehst du, was da steht? Wenn nicht, frag nochmal konkret.

Warum willst du das Factory-Pattern einsetzen? Warum machst du nicht einfach new Ant und so weiter?

Und warum hast du alle Klassen von einer gemeinsamen Basis abgeleitet? Was ist das Gemeinsame an all diesen Klassen?

Dieser Post wurde am 19.01.2018 um 20:52 Uhr von ao editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
015
19.01.2018, 21:29 Uhr
Sandra39



Das Gemeinsame dieser Klassen ist, dass sie alle vom Typ Item sind und eine Methode act() haben, die eine kurze Beschreibung ausgibt. Vielleicht überleg ich mir noch etwas anderes, aber das dient erstmal nur zu Übungszwecken.

Das Factory Pattern deshalb, weil die createItem() Methode immer die gleiche ist. Das dient auch nur zu Übungszwecken. Ob das bei dem Projekt sinnvoll ist, sei mal dahingestellt.

Ich brauch jetzt noch zwei Klassen, also die Factory (Erzeuger) selber und eine, die von Factory abgeleitet (konkreter Erzeuger) ist. Hab ich das so richtig verstanden?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
016
20.01.2018, 11:33 Uhr
ao

(Operator)



Zitat von Sandra39:
Das Gemeinsame dieser Klassen ist, dass sie alle vom Typ Item sind und eine Methode act() haben, die eine kurze Beschreibung ausgibt.

Meinetwegen, wenn man davon ausgeht, dass Futter, Pheromon und Ameisenhügel "agieren" können ...

Übungszwecke sind natürlich OK, aber pass auf, dass du dein Design nicht zu sehr verbiegst, nur um Übungen zu machen.

Basisklassen von diesem Abstraktionslevel sind eigentlich keine Klassen in dem Sinne, dass sie gemeinsame Funktionalität verallgemeinern. Sie definieren nur Schnittstellen, d.h. Methodenköpfe und Typen. Konvention ist, die Namen solcher Klassen mit "I" zu prefixen, damit sichtbar ist, dass sie ein Interface darstellen. Also class IItem. Und man sollte aufpassen, dass man tatsächlich nur Schnittstellencode in ein Interface hineinschreibt und nicht etwa doch Variablen oder Funktionscode. Der Compiler verhindert das nicht, es ist wie gesagt nur eine Konvention.

In anderen Sprachen (C#, Java) gibt es hierfür ein eigenes Schlüsselwort "interface", das an Stelle von "class" verwendet wird, und wenn man da Code hineinschreibt, gibts Compilerfehler.


Zitat:
Das dient auch nur zu Übungszwecken. Ob das bei dem Projekt sinnvoll ist, sei mal dahingestellt.

OK.


Zitat:
Ich brauch jetzt noch zwei Klassen, also die Factory (Erzeuger) selber und eine, die von Factory abgeleitet (konkreter Erzeuger) ist. Hab ich das so richtig verstanden?

Du brauchst zu jeder der Item-Ableitungen eine eigene konkrete Erzeugerklasse.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
017
20.01.2018, 23:55 Uhr
f.-th.



Hab gerade mal im Netz nach ein paar Code-Schnipseln aus dem Buch C++ für Spieleprogrammierer von Heiko Kalista gesucht. Die Beispiele, die ich fand, zeigen einen sehr alten C++ Stil! Aus aktueller C++ Sicht ein ist das ein (schrecklicher) Mix aus C und C++. Keine Ahnung ob die aktuelle Auflage heute besser ist?

Das hat ao aber schon hier angedeutet.

Ich versuche mal ao's Quelltext ohne C Relikte:

C++:
// ------------------- environment.h

#ifndef ENVIRONMENT_H_INCLUDED
#define ENVIRONMENT_H_INCLUDED

class Environment {
    public:
        int width;
        int height;

        Environment(int h, int w);

        ~Environment() {
        }

        void display_coordinates(int height, int width);
};

#endif  ENVIRONMENT_H_INCLUDED

//    ------------------ environment.cpp

#include <iostream>
#include <iomanip>
#include "environment.h"


using namespace std;

Environment::Environment(int h, int w)
: width (w)
, height (h)
{

}

void Environment::display_coordinates(int height, int width) {
    int matrix[10][10] = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
                         {11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
                         {21, 22, 23, 24, 25, 26, 27, 28, 29, 30},
                         {31, 32, 33, 34, 35, 36, 37, 38, 39, 40},
                         {41, 42, 43, 44, 45, 46, 47, 48, 49, 50},
                         {51, 52, 53, 54, 55, 56, 57, 58, 59, 60},
                         {61, 62, 63, 64, 65, 66, 67, 68, 69, 70},
                         {71, 72, 73, 74, 75, 76, 77, 78, 79, 80},
                         {81, 82, 83, 84, 85, 86, 87, 88, 89, 90},
                         {91, 92, 93, 94, 95, 96, 97, 98, 99, 100}};

    int i, j;

    for(i = 0; i < height; i++) {
        for(j = 0; j < width; j++) {
           cout << setw(4) << matrix[i][j];
        }
        cout << endl;
    }
}

//    -------------- main.cpp

#include <iostream>
#include "environment.h"

using namespace std;

static void PrintMenu ()
{
...
}

int main(int argc, char *argv[]) {
...
}


Die gekürzten Passagen seht ao's letzten Quelltext.

Hoffe mal das das ohne Vorschau lesbar ist?

Zusammmenfassung:
Möglichst

C++:
using namespace std;


in eigenen Headern vermeiden => erleichtert bei grösseren C++ Projekten die Fehlersuche.

C Header sollten in keinem aktuellen C++ Quelltext zu finden sein!

Leider werden im Netz, teilweise mit sehr guten "Kritiken" versehene, schlechte C++ Beispiele gezeigt. Wenn man beruflich mit C++ arbeitet, sollte man diesen C - C++ Mix lesen und verstehen können, aber heute nicht mehr so schreiben.

MfG
f.-th.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
018
22.01.2018, 10:02 Uhr
ao

(Operator)



Zitat von f.-th.:
Hab gerade mal im Netz nach ein paar Code-Schnipseln aus dem Buch C++ für Spieleprogrammierer von Heiko Kalista gesucht. Die Beispiele, die ich fand, zeigen einen sehr alten C++ Stil!

Gute Idee, das Buch mal zu googeln. Hab ich auch am WE gemacht und hatte den gleichen Eindruck. Das gilt für die Beispiele, die auf der Verlagsseite (hanser-fachbuch.de) für die aktuelle 5. Auflage (2016) publiziert werden.

Bei C++ hat sich in den letzten Jahren so viel verändert, dass es wohl nicht mehr reicht, eine Neuauflage nur zu "aktualisieren" und zu "erweitern". Bücher von vor 2010 müssten eigentlich ganz neu geschrieben werden, was aber voraussetzt, dass die Verlage kräftig investieren und dass die Autoren ihr althergebrachtes Wissen von Grund auf erneuern - eine Erkenntnis, die vielleicht erst noch reifen muss.

Das "alte" Konzept war, erst mal auf 300 Seiten die Sprache C einzuführen, Variablen, Typen, Kontrollstrukturen, Funktionen, Zeiger, Arrays usw. Nachteil: Bis im 10. Kapitel zum ersten Mal das Wort "class" fällt und Vererbung im 12. und Templates frühestens im 16. Kapitel drankommen, haben die Schüler sich so viele prozedurale Oldschool-Techniken angewöhnt, dass man ihnen kaum noch erklären kann, warum sie mit OO auf einmal alles anders machen sollen. Das wirft sie nämlich zurück bis fast auf Null, und dass die Lehrer-Generation diese Erfahrung machen musste (weil sie zuerst C gelernt und irgendwann später auf C++ umgeschult hat), heißt nicht, dass das die natürliche Evolution ist.

Es müsste anders laufen. Klassen müssten von vornherein zum selbstverständlichen Umgang gehören, und Templates auch frühestmöglich, damit die Schüler sich von Anfang an an std::vector<int> und make_shared<T> gewöhnen und gar nicht erst an den alten "Dreck". Um den kann man sich später in einem gesonderten Abschnitt "Umgang mit C-Bibliotheken" kümmern. Ich glaube, das wäre eine bessere Reihenfolge.

Dieser Post wurde am 22.01.2018 um 10:55 Uhr von ao editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
019
22.01.2018, 11:20 Uhr
Sandra39



Danke für die Information. Wir hatten jetzt ein Jahr lang C am Studiengang Informatik und seit dem 3. Semester C++. In C mussten wir Listen (einfach, doppelt) mühsam selbst verketten, was ja jetzt nicht schlecht sein muss. Das Problem sehe ich nur in dem, dass man nach einem Jahr die Sprache noch nicht so gut beherrscht und dann gleich eine neue lernt.

Das ist leider nicht das einzige Fach. In Webtechnologien hatten wir innerhalb eines Semesters php, Javascript und vue ".

Meine Frage ist nun, welches Buch ist nun ein gutes Lehrbuch? Im Internet habe ich von Jürgen Wolf sehr viele schlechte Kritiken gelesen. Ich glaub, das war sogar hier im Forum.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: [ 1 ] > 2 < [ 3 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: