Include über Kreuz
-
Hallo zusammen.
Ich weiß, das Thema wurde schon dutzende Male besprochen, aber nach mehreren Stunden suchen und probieren komme ich auf keinen grünen Zweig.
Ich habe eine Klasse "threadClass", welche einen Thread kapselt. Eine andere Klasse "caller" hat je eine Instanz dieser threadClass. Die threadClass soll aber wiederum eine Methode der Klasse "caller" aufrufen. Damit habe ich das klassische Problem, dass ich die Files gegenseitig includen müsste. Ich habe es auch schon mit Vorwärtsdeklarationen probiert, vergebens. Der Compiler sagt dann "Verwendung des undefinierten Types..."
caller.h
#ifndef _CALLER_H_ #define _CALLER_H_ #include <iostream> using namespace std; class threadClass; class caller { public: caller(int myNumber); ~caller(); void startThread(); virtual void threadCallbackFunction(int num); private: int n; threadClass* myThread; }; #endifcaller.cpp
#include "caller.h" caller::caller(int myNumber) { n = myNumber; } caller::~caller() { myThread->kill(); // Ich weiß, hier muss ich noch sauber auf die Beendigung warten delete(myThread); } void caller::startThread() { myThread = new threadClass(); } void caller::threadCallbackFunction(int num) { cout << "Hello from caller " << n << " (" << num << " times called)" <<endl; }threadClass.h
#ifndef _THREADCLASS_H_ #define _THREADCLASS_H_ #include <Windows.h> #include "caller.h" class threadClass { public: threadClass(caller* classptr); ~threadClass(); void start(); void kill(); virtual DWORD ThreadFunction(void); private: HANDLE hThread; DWORD dwThreadID; LPVOID pParam; bool killThread; caller* cptr; int execNumber; enum Status { STOPPED, RUNNING, SUSPENDING }; int status; protected: static DWORD WINAPI StaticThreadFunction(void* pthis); }; #endifthreadClass.cpp
#include "threadClass.h" threadClass::threadClass(caller* classptr) { killThread = false; cptr = classptr; execNumber = 0; } threadClass::~threadClass() {} void threadClass::start() { if (status == RUNNING) { // Thread is running return; } else if (status == SUSPENDING) { // Thread continue status = RUNNING; ResumeThread(hThread); } else { // Thread start status = RUNNING; hThread = CreateThread( NULL, 0, StaticThreadFunction, this, 0, &dwThreadID); } } void threadClass::kill() { killThread = true; } DWORD threadClass::ThreadFunction(void) { while (!killThread) { execNumber++; cptr->threadCallbackFunction(execNumber); } return 0; } DWORD WINAPI threadClass::StaticThreadFunction(void* pthis) { threadClass *pThis; pThis = (threadClass *) pthis; // Ich weiß. Ist ein C cast. return pThis->ThreadFunction(); }Wie muss ich das strukturieren, damit es funktioniert?
Ich habe auch schon mehrfach die Meinung gehört, dass das schlechtes Design ist. Allerdings wüsste ich nicht, wie ich es anderes lösen soll.
Ich möchte die Thread-Geschichte in einer separaten Klasse haben, damit ich sie auch nach dem gleichen Mechanismus für andere Aufrufer-Klassen einsetzen kann (dann durch Vererbung oder Templates).Grüße,
Ziu
-
Also bei einer Vorwärtsdeklartaion musst du trotzdem das file dann in der cpp includieren.
-
Haut trotzdem nicht hin.
Dann kennt der Compiler die Klasse "caller" nicht.
-
und was sagt der compiler und in welcher Zeile?
-
Im cpp musst du natürlich dann den Header einbinden.
Also in caller.cpp muss threadClass.h inkludiert werden.
-
Hei du Jockel lies mal 4 Beiträge weiter oben.
-
Ja, wäre wohl schlauer gewesen

-
Also ich hab jetzt:
caller.h
#include "threadClass.h"
Vorwärtsdeklaration: class threadClass;caller.cpp
#include "caller.h"
#include "threadClass.h"threadClass.h
#include "caller.h"threadClass.cpp
#include "threadClass.h"
#include "caller.h"Ergebnis:
1>Kompilieren...
1>caller.cpp
1>...\threadstandalone\threadclass.h(10) : error C2061: Syntaxfehler: Bezeichner 'caller'
1>...\threadstandalone\threadclass.h(23) : error C2143: Syntaxfehler: Es fehlt ';' vor '*'
1>...\threadstandalone\threadclass.h(23) : error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterstützt.
1>...\threadstandalone\threadclass.h(23) : error C4430: Fehlender Typspezifizierer - int wird angenommen. Hinweis: "default-int" wird von C++ nicht unterstützt.
1>threadClass.cpp
1>Code wird generiert...
1>threadStandalone - 4 Fehler, 0 Warnung(en)
========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========
-
hey,
Wenn du threadClass als vorwärtsdekleration hast, darfst/musst du es nicht mehr includieren in der h-Datei.
Wenn du caller in der threadClass.h includierst, brauchst du es nicht mehr in der threadClass.cpp zu includiern.
-
So sollte es gehen:
in threadclass.h:
class caller; // Forward declarationin caller.h
class threadclass; // Forward declarationin threadclass.cpp
#include "caller.h"in caller.cpp
#include "threadclass.h"
-
Ich verweis immer gerne hier hin:
Definitionen und Deklarationen in C++
-
Source2702 schrieb:
So sollte es gehen:
in threadclass.h:
class caller; // Forward declarationin caller.h
class threadclass; // Forward declarationin threadclass.cpp
#include "caller.h"in caller.cpp
#include "threadclass.h"Nein, geht auch nicht...
1>------ Erstellen gestartet: Projekt: threadStandalone, Konfiguration: Debug Win32 ------
1>Kompilieren...
1>caller.cpp
1>...\threadstandalone\threadstandalone\caller.cpp(3) : error C2027: Verwendung des undefinierten Typs "caller"
1> ...\threadstandalone\threadclass.h(6): Siehe Deklaration von 'caller'
1>...\threadstandalone\caller.cpp(3) : error C2062: 'int'-Typ unerwartet
1>...\threadstandalone\caller.cpp(4) : error C2143: Syntaxfehler: Es fehlt ';' vor '{'
1>...\threadstandalone\caller.cpp(4) : error C2447: '{': Funktionsheader fehlt - Parameterliste im alten Stil?
1>...\threadstandalone\caller.cpp(8) : error C2027: Verwendung des undefinierten Typs "caller"...
1>Code wird generiert...
1>Kompilieren...
1>main.cpp
1>Code wird generiert...
1>threadStandalone - 61 Fehler, 1 Warnung(en)
========== Erstellen: 0 erfolgreich, Fehler bei 1, 0 aktuell, 0 übersprungen ==========
-
caller.h hast aber in caller.cpp schon inkludiert, oder?
-
Wollte ich gerade schreiben, da lag der letzte Fehler.
Jetzt klappt's, danke sehr.
-
So, nochmal für alle, die diesen Thread in der Zukunft besuchen und die endgültige Lösung wissen wollen:
// threadClass.h class caller; // caller.h class threadClass; // threadClass.cpp #include "caller.h" #include "threadClass.h" // caller.cpp #include "threadClass.h" #include "caller.h"So läuft's bei mir jedenfalls, mit MS Visual Studio 2008.
Nochmal vielen Dank an alle Helfer!
-
Äusserst merkwürdiges Konstrukt. Lies doch meinen verlinkten Artikel durch und probier das erneut. Es kann nicht sein, dass man von aussen solche Vorwärtsdeklarationen machen muss.