Basisklasse undefiniert | Compilerwarnung
-
Hallo!
Klasse MultiplacationTrainer erbt von RechenTrainer.
es kommt zu einer Fehlermeldung.
1>------ Neues Erstellen gestartet: Projekt: RechenTrainerOO, Konfiguration: Debug Win32 ------
1>Die Zwischen- und Ausgabedateien für das Projekt "RechenTrainerOO" mit der Konfiguration "Debug|Win32" werden gelöscht.
1>Kompilieren...
1>main.cpp
1>Menu.cpp
1>MultiplikationTrainer.cpp
1>RechenTrainer.cpp
1>w:\c++\workspace\rechentrainer\rechentraineroo\multiplikationtrainer.h(7) : error C2504: 'RechenTrainer': Basisklasse undefiniert
1>Code wird generiert...
1>Das Buildprotokoll wurde unter "file://w:\C++\workspace\RechenTrainer\RechenTrainerOO\Debug\BuildLog.htm" gespeichert.
1>RechenTrainerOO - 1 Fehler, 0 Warnung(en)
========== Alles neu erstellen: 0 erfolgreich, Fehler bei 1, 0 übersprungen ==========Ich poste mal alle klassen...
#ifndef RECHENTRAINER #define RECHENTRAINER #include "Menu.h" #include <ctime> #include <sstream> #include <iostream> #include <cstdlib> class Menu; struct Status; class RechenTrainer{ protected: bool _addNow; int random(); public: RechenTrainer(void); virtual ~RechenTrainer(void); void rechne(Menu* menu); }; #endif#include "RechenTrainer.h" using namespace std; RechenTrainer::RechenTrainer(void){ } RechenTrainer::~RechenTrainer(void){ } void RechenTrainer::rechne( Menu* menu){ cout << "Addition/Substraktionstraining\n"; while(menu->_status._tasks-- > 0){ int a = random(); int b = random(); int result; if(_addNow){ result = a+b; } else { result = a-b; } stringstream ss_a; stringstream ss_b; string str = ""; ss_a << a; str += ss_a.str(); str += ((_addNow) ? " + " : " - "); ss_b << b; str += ss_b.str(); str += " = "; cout << str ; int userResult = menu->numberFromUser(); stringstream ss_user; ss_user << userResult; str += ss_user.str(); if(userResult == result){ cout << "richtig " << result; str += " richtig "; } else { cout << " falsch " << result; str += " falsch "; stringstream temp; temp << result; str += temp.str(); } cout << endl; _addNow = !_addNow; menu->_status._overallTasks++; }//while } int RechenTrainer::random(){ int random_integer = (rand() % 100) +1; return random_integer; }#ifndef MULTITRAINER #define MULTITRAINER #include "RechenTrainer.h" class Menu; class MultiplikationTrainer : public RechenTrainer{ public: MultiplikationTrainer(void); ~MultiplikationTrainer(void); void rechne(Menu* menu); }; #endif#include "MultiplikationTrainer.h" MultiplikationTrainer::MultiplikationTrainer(void) { } MultiplikationTrainer::~MultiplikationTrainer(void) { } void MultiplikationTrainer::rechne( Menu* menu){ cout << "Addition/Substraktionstraining\n"; while(menu->_status._tasks-- > 0){ int a = random(); int b = random(); int result = a*b;; stringstream ss_a; stringstream ss_b; string str = ""; ss_a << a; str += ss_a.str(); str += " * "; ss_b << b; str += ss_b.str(); str += " = "; cout << str ; int userResult = menu->numberFromUser(); stringstream ss_user; ss_user << userResult; str += ss_user.str(); if(userResult == result){ cout << "richtig " << result; str += " richtig "; } else { cout << " falsch " << result; str += " falsch "; stringstream temp; temp << result; str += temp.str(); } cout << endl; menu->_status._overallTasks++; }//while }
-
Bindet die Menu.h (möglicherweise indirekt) die MultiplikationTrainer.h ein?
-
ja du hast recht, dran lags. ich brauche die aber im Menu

P.S. wieso kommt es aber dann zum Fehler?
-
Dit_ schrieb:
P.S. wieso kommt es aber dann zum Fehler?
Da bindet die RechenTrainer.h die Menu.h ein, diese bindet die MultiplikationTrainer.h ein, diese versucht die RechenTrainer.h einzubinden, aber dort sind nun die Includeguards aktiviert worden und daher passiert nicht und die Basisklasse ist nicht bekannt, wenn sie gebraucht wird.
ich brauche die aber im Menu

Solche zyklischen Abhängigkeiten kann man eigentlich immer auflösen. Denk dran, dass du nicht immer die volle Definition brauchst, eine Vorwärtsdeklaration reicht oft auch. Ich sehe, du machst davon schon reichlich gebrauch, bindest aber trotzdem noch die entsprechenden Header ein. Ich sehe gar nicht, wozu die Menu.h in der RechenTrainer.h benötigt wird.
-
menu hat mehrere Rechentrainer
#ifndef MENU #define MENU #include "RechenTrainer.h" #include "MultiplikationTrainer.h" #include <iostream> #include <string> #include <cstdlib> #include <map> using namespace std; class Menu{ public: Menu(void); ~Menu(void); /** * Speichert die Informationen über die Anzahl der Aufgaben * und die Anzahl der richtigen Lösungen */ struct Status { int _overallTasks; int _tasks; int _points; Status(){ reset(); } void reset(){ _overallTasks = 0; _tasks = 5; _points = 0; } }; char getInput(); void training(); void printStatus(); int resultInPercent(); int numberFromUser() const; Status _status; private: void printMenu(); void setTaskCount(); }; #endif#include "Menu.h" Menu::Menu(void){ } Menu::~Menu(void){ } void Menu::printMenu(){ std::cout << "################## M E N U ##################" << std::endl; std::cout << "# ~: Addition/Substraktion" << std::endl; std::cout << "# *: Multiplikation" << std::endl; std::cout << "# ?: Wahrsager" << std::endl; std::cout << "# ----------" << std::endl; std::cout << "# t: Anzahl der Aufgaben Aendern. [Aktuell: "<< _status._tasks <<"]" << std::endl; std::cout << "# p: Punkte ausgeben" << std::endl; std::cout << "# q: Beenden" << std::endl; std::cout << "#############################################" << std::endl; } char Menu::getInput(){ char input; cin >> input; return input; } int Menu::numberFromUser() const{ //TODO } void Menu::setTaskCount(){ //TODO } void Menu::training(){ map <char, RechenTrainer*> trainerMap; trainerMap['~'] = new RechenTrainer(); // trainerMap['*'] = new MultiplikationTrainer(); RechenTrainer* _currentTrainer; printMenu(); while(true){ char ch = getInput(); switch(ch){ case 't': setTaskCount(); break; case 'p': printStatus(); break; case 'q': std::cout << "Programm wird beendet..." << std::endl; return; default: _currentTrainer = trainerMap[ch]; if(_currentTrainer == 0){ std::cout << "Unbekannter Befehl" << std::endl; continue; } else { _currentTrainer->rechne(this); } }//switch printStatus(); _status.reset(); printMenu(); }//while } int Menu::resultInPercent(){ //dreifache-liniare-optimierung return 100*_status._points /_status._overallTasks; } void Menu::printStatus(){ //TODO }
-
In der menu.h sehe ich überhaupt nichts, was die Rechentrainer verwenden will - dort brauchst du vermutlich nicht einmal Forward-Deklarationen. Wenn du die Trainer bei der Implementation des Menüs benötigst, reicht es, sie genau dort (in der menu.cpp) einzubinden.
-
ok vielen Dank! :p
-
In deiner Methode
Menu::training()erzeugst du ein Speicherleck. Du allozierst dynamisch ein Trainer Objekt und legst es in die Map (Zeile 36), rufst für dieses Objekt allerdings keinedeleteauf. Entweder solltest du am Ende der Methode über alle Elemente der map laufen und die Elemente perdeletelöschen, oder du verwendest geeignete Pointer (shared- / unique_pointer), oder du verwendest den passenden pointer_container aus den boost Bibliotheken (falls verfügbar).