Frage

Ich mag ein paar „statischen“ Methoden einer CPP-Klasse in einer anderen Datei definiert nennen, aber ich habe die Verknüpfung Probleme. Ich habe einen Test-Fall, der mein Problem und den Code neu erstellt für sie ist unten.

(Ich bin ganz neu in C ++, ich komme aus einem Java-Hintergrund, und ich bin ein wenig vertraut mit C).

// CppClass.cpp
#include <iostream>
#include <pthread.h>

static pthread_t thread;
static pthread_mutex_t mutex;
static pthread_cond_t cond;
static int shutdown;

using namespace std;

class CppClass
{
public:
        static void Start()
        {
                cout << "Testing start function." << endl;
                shutdown = 0;
                pthread_attr_t attr;
                pthread_attr_init(&attr);
                pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
                pthread_mutex_init(&mutex, NULL);
                pthread_cond_init(&cond, NULL);

                pthread_create(&thread, &attr, run_thread, NULL);
        }

        static void Stop()
        {
                pthread_mutex_lock(&mutex);
                shutdown = 1;
                pthread_cond_broadcast(&cond);
                pthread_mutex_unlock(&mutex);
        }

        static void Join()
        {
                pthread_join(thread, NULL);
        }
private:
        static void *run_thread(void *pthread_args)
        {
                CppClass *obj = new CppClass();
                pthread_mutex_lock(&mutex);
                while (shutdown == 0)
                {
                        struct timespec ts;
                        ts.tv_sec = time(NULL) + 3;
                        pthread_cond_timedwait(&cond, &mutex, &ts);
                        if (shutdown)
                        {
                                break;
                        }
                        obj->display();
                }
                pthread_mutex_unlock(&mutex);
                pthread_mutex_destroy(&mutex);
                pthread_cond_destroy(&cond);
                pthread_exit(NULL);
                return NULL;
        }

        void display()
        {
                cout << " Inside display() " << endl;
        }
};

// main.cpp
#include <iostream>
/* 
 * If I remove the comment below and delete the
 * the class declaration part, it works.
 */
// #include "CppClass.cpp"
using namespace std;

class CppClass
{
public:
        static void Start();
        static void Stop();
        static void Join();
};

int main()
{
        CppClass::Start();
        while (1)
        {
                int quit;
                cout << "Do you want to end?: (0 = stay, 1 = quit) ";
                cin >> quit;
                cout << "Input: " << quit << endl;
                if (quit)
                {
                        CppClass::Stop();
                        cout << "Joining CppClass..." << endl;
                        CppClass::Join();
                        break;
                }
        }
}

Als ich zu kompilieren versucht, bekomme ich folgende Fehlermeldung:

$ g++ -o go main.cpp CppClass.cpp -l pthread
/tmp/cclhBttM.o(.text+0x119): In function `main':
: undefined reference to `CppClass::Start()'
/tmp/cclhBttM.o(.text+0x182): In function `main':
: undefined reference to `CppClass::Stop()'
/tmp/cclhBttM.o(.text+0x1ad): In function `main':
: undefined reference to `CppClass::Join()'
collect2: ld returned 1 exit status

Aber wenn ich die Klassendeklaration in main.cpp entfernen und ersetzen sie durch #include „CppClass.cpp“, es funktioniert gut. Grundsätzlich möchte ich diese Erklärungen in einer separaten .h-Datei setzen und nutzen. Bin ich etwas fehlt?

Danke für die Hilfe.

War es hilfreich?

Lösung

Es ist offensichtlich, dass du von einem Java-Hintergrund kommen, weil Sie noch nicht haben das Konzept der Header-Dateien erfaßt. In Java der Prozess etwas zu definieren, ist in der Regel in einem Stück. Sie erklären und zugleich definieren. In C / C ++, es ist ein zweistufiger Prozess. Deklarieren etwas sagt der Compiler „etwas mit dieser Art existiert, aber ich werde Ihnen später sagen, wie es tatsächlich umgesetzt wird“. definieren etwas ist der Compiler die tatsächliche Implementierung Teil geben. Header-Dateien verwendet werden, vor allem für Erklärungen, CPP-Dateien für Definitionen.

Header-Dateien gibt es die „API“ von Klassen zu beschreiben, aber nicht ihre eigentliche Code. Es ist möglich, Code in der Kopfzeile enthält, der Kopf inlining genannt wird. Sie haben alles in CppClass.cpp inlined (nicht gut, Header-inlining sollte die Ausnahme sein), und dann erklären Sie Ihre Klasse in main.cpp AGAIN, die eine doppelte Erklärung in C ++ ist. Der inlining in der Klasse Körper führt reduplication zu codieren jedes Mal verwenden Sie eine Methode (dies ist nur Sounds verrückt. Siehe C ++ auf FAQ-Bereich Details inlining.)

Einschließlich der Doppel Erklärung im Code erhalten Sie einen Compiler-Fehler. Beim Verlassen des Klassencode kompiliert, sondern gibt Ihnen einen Fehler Linker, weil jetzt nur Sie die Kopf wie Klassendeklaration in main.cpp haben. Der Linker sieht keinen Code, die Klassenmethoden implementiert, das ist, warum die Fehler erscheinen. Anders als in Java, die C ++ Linker nicht automatisch für das Objekt suchen Dateien, die er verwenden möchte. Wenn Sie Klasse XYZ verwenden und geben Sie es nicht Code für XYZ-Objekt, es wird einfach fehlschlagen.

Bitte schauen Sie unter Wikipedias Header-Datei Artikel und Header-Datei Patterns (der Link auch an der Unterseite des Wikipedia-Artikel und enthält weitere Beispiele)

Kurz gesagt:

Für jede Klasse erzeugt eine NewClass.h und NewClass.cpp Datei.

In der NewClass.h Datei schreiben:

class NewClass {
public:
   NewClass();
   int methodA();
   int methodB();
}; <- don't forget the semicolon

In der NewClass.cpp Datei schreiben:

#include "NewClass.h"

NewClass::NewClass() {
  // constructor goes here
}

int NewClass::methodA() {
  // methodA goes here
  return 0;
}

int NewClass::methodB() {
  // methodB goes here
  return 1;
}

In main.cpp, schreiben Sie:

#include "NewClass.h"

int main() {
  NewClass nc;
  // do something with nc
}

Um sie alle zusammen zu verbinden, tun ein

g ++ -o NewClassExe NewClass.cpp main.cpp

(nur ein Beispiel mit gcc)

Andere Tipps

Sie definieren die Klasse zweimal, was ich ziemlich sicher bin, funktioniert nicht.

Versuchen Sie etwas wie folgt aus:

Zuerst wird eine Header-Datei CppClass.h:

// CppClass.h
using namespace std;

class CppClass
{
public:
    static void Start();
    static void Stop();
    static void Join();
private:
    void *run_thread(void *pthread_args);
    void display();
};

Dann wird eine CppClass.cpp Datei deren Umsetzung:

// CppClass.cpp
#include <iostream>
#include <pthread.h>
#include "CppClass.h"

using namespace std;

void CppClass::Start()
{
    /* method body goes here */
}
void CppClass::Stop()
{
    /* method body goes here */
}
void CppClass::Join()
{
    /* method body goes here */
}
void *CppClass::run_thread(void *pthread_args)
{
    /* method body goes here */
}
void CppClass::display() {
    /* method body goes here */
}

Dann ist Ihre Hauptdatei:

// main.cpp
#include "CppClass.h"

int main()
{
    /* main method body here */
}

Ich glaube, der g ++ Aufruf gleich sein würde.

Grundsätzlich kann man nicht die gleiche Klasse deklariert zweimal. Sie sollten die Klasse in der Header-Datei deklarieren, dann die Umsetzung in der CPP-Datei deklarieren. Sie können auch die gesamten Code inline in einer Single Deklaration der Klasse in einer Header-Datei setzen. Aber es erklärt zweimal wie Sie nicht funktioniert wird.

Ich hoffe, dass Sinn gemacht ...

Ich glaube, Sie etwas tun wollen wie:

g ++ -c CppClass.cpp g ++ -c main.cpp g ++ -o gehen main.o CppClass.o

Das sollte es lösen.

macht eine .h-Datei mit der Klassendefinition in ihm, und dann # include diese Datei in Ihre 2-Dateien.

Sicher sieht aus wie der Linker nicht Sie zweite Quelldatei aufnimmt.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top