Frage

Ich schuf diese neue Klasse :

//------------------------------------------------------------------------------
#ifndef MULTITHREADEDVECTOR_H
#define MULTITHREADEDVECTOR_H
//------------------------------------------------------------------------------
#include <vector>
#include <GL/GLFW.h>
//------------------------------------------------------------------------------
template<class T>
class MultithreadedVector {

    public:

        MultithreadedVector();

        void push_back(T data);

        void erase(typename std::vector<T>::iterator it);

        std::vector<T> get_container();
    private:

        std::vector<T> container_;
        GLFWmutex th_mutex_;


};
//------------------------------------------------------------------------------
#endif // MULTITHREADEDVECTOR_H_INCLUDED
//------------------------------------------------------------------------------

Die definition der Klasse :

//------------------------------------------------------------------------------
#include "MultithreadedVector.h"
//------------------------------------------------------------------------------
using namespace std;
//------------------------------------------------------------------------------
template<class T>
MultithreadedVector<T>::MultithreadedVector() {

    th_mutex_ = glfwCreateMutex();
}

template<class T>
void MultithreadedVector<T>::push_back(T data) {

    glfwLockMutex(th_mutex_);
    container_.push_back(data);
    glfwUnlockMutex(th_mutex_);

}

template<class T>
void MultithreadedVector<T>::erase(typename vector<T>::iterator it) {

    glfwLockMutex(th_mutex_);
    container_.erase(it);
    glfwUnlockMutex(th_mutex_);
}

template<class T>
vector<T> MultithreadedVector<T>::get_container() {


    return container_;

}

Das problem ist jetzt, dass wenn ich versuche, es in meinem code als statisches Mitglied einer anderen Klasse :

// VehicleManager.h
#ifndef MULTITHREADEDVECTOR_H
#define MULTITHREADEDVECTOR_H

#include "MultithreadedVector.h"
#include "Vehicle.h"
class Foo {

   public:
     // stuffs
   private:
     static MultithreadedVector<Vehicle> vehicles_; 
     ...
}

#endif

Drinnen dann :VehicleManager.cpp

#include "VehicleManager.h"

MultithreadedVector<Vehicle> VehicleManager::vehicles_;

void VehicleManager::Method() {

  Vehicle vehicle;
  VehicleManager::vehicles_.push_back(vehicle);

}

Aber es wird nicht kompiliert :(, ich bekomme diese Fehlermeldung msg jedesmal, wenn :

C:\***\VehicleManager.cpp|188|undefined reference to `MultithreadedVector<Vehicle>::push_back(Vehicle)'|

Ich verstehe wirklich nicht, warum, vor allem, dass ich definiert die statische Klasse Mitglied im globalen Rahmen VehicleManager.cpp.

PS:Ich verwende Code::Blocks.

Vielen Dank !

War es hilfreich?

Lösung

Das ist, was passiert, wenn blind verschieben einer Klasse-Vorlage-Implementierung, um eine cpp-Datei.

Zu machen, dass die arbeiten, müssen Sie genau wissen, für welche Arten von T instanziieren Sie die Klasse, Vorlage und geben Sie diese in die cpp-Datei.

In diesem Fall, setzen Sie diese in der cpp-Datei:

template class MultithreadedVector<Vehicle>;

Beachten Sie, dass die cpp-Datei muss wissen, über Vehicle dann.

Andere Tipps

Die meisten C++ - Compiler nicht zu erlauben, Sie zu trennen Vorlage von Erklärungen und Vorlage definitiions.Sie müssen die vollständige definition der template-Klassen in einem einzigen .h-Datei, und nicht teilen Sie Sie in .h-und .cpp-Dateien.

Der vollständige code der Vorlage Umsetzung muss sichtbar sein, um den compiler an der Stelle sieht er die Verwendung der Vorlage, so kann es instanziieren der Vorlage und kompilieren es in Objekt-code, die später miteinander verbunden.

Definieren Sie die template-code in der gleichen header-Datei als template deklariert ist.

Ich denke, es gibt zwei Fälle, wie kann man die Verwendung von Vorlagen

  1. Die Bereitstellung von generischen code für eine beliebige Anzahl von konform-Typen
  2. Die Bereitstellung von generischen code für eine Feste Gruppe von Arten

Für die zweite, Sie müssen nicht Vorlagen in der Kopfzeile:Da Sie wissen im Vorfeld genau, mit welchen Arten Ihre Vorlage verwendet wird.Sie können sehr gut definieren Sie eine Klasse template-member-Funktion, oder-Funktion-Vorlage in eine separate übersetzungseinheit, ohne linker-Fehler.Manche Leute halten die Lehre, dass andere dies nicht möglich ist, und verwirren die Sache von dieser.

Aber ich denke, es hängt von diesen beiden Fällen, ob Sie getrennte Deklaration und definition in verschiedenen übersetzungseinheiten oder nicht.

  • Wenn Sie verwenden möchten, Falle 1, Sie wollen immer die definition im Kopf (ob durch spezielle benannte Dateien, wie .ipp, .tcc oder was auch immer).Ich weiß nur von einem C++ - frontend unterstützt die Trennung definition von Erklärungen auch in diesem Fall, die ist die EDG (edison design group) - frontend verwendet, die von intel und der comeau-Compiler implementieren export.Das Stichwort ist als ein misfeature durch einige, und die meisten Compiler nicht, es umzusetzen.

  • Und wenn Sie wollen, zu verwenden, Fall 2, es ist nicht gut, um die Definitionen in den header, da gäbe es keinen Grund, dies zu tun:Sie wird nur explizit zu instanziieren, die die benötigten Funktionen und Klassen für die Feste Gruppe von Arten.In diesem zweiten Fall verwenden Sie die Vorlage um dich selbst zu retten von der Last zur Aufrechterhaltung möglicherweise redundante code, und die Möglichkeit haben, offen führen spezielle Verhalten für einige Arten in einigen Fällen.

Ihr Szenario ist eindeutig ein Fall 1 situation, und so haben Sie Ihre Definitionen in den header.

Sie scheinen zu haben, ein copy&paste Fehler in VehicleManager.h:

#ifndef MULTITHREADEDVECTOR_H
#define MULTITHREADEDVECTOR_H

Diese verbietet die Einbindung der header-Datei, wo die Foo-Klasse definiert ist.

Sie können schreiben, die Vorlage Umsetzung in der cpp-Datei in den meisten Fällen.Verschieben Sie die Vorlage Umsetzung der header-Datei, so dass der compiler instanziiert werden kann es richtig.

Abgesehen von den anderen Antworten:

Sie müssen guard get_container() wie gut.Diese Methode, im Grunde Kopien der container_ Elemente, daher müssen bewacht werden.

template<class T>
vector<T> MultithreadedVector<T>::get_container() 
{
    return container_;
}

Eine Vorlage ist eine Art erweiterte, spezielle Art von makro.Sie können nicht wirklich kompilieren einer Vorlage defintion getrennt, wie es aussieht, die Sie versuchen zu tun.

Für die meisten Menschen, dies bedeutet, dass Sie nicht einmal die Mühe, Sie zu trennen teplate Definitionen aus Ihren Erklärungen.Ich habe einen co-Arbeiter geht hier noch einen Schritt weiter, und weigert sich zu trennen nicht-Vorlage Definitionen und Erklärungen zu.

Wenn Sie wollen, um die definition einer Vorlage aus der Erklärung, Sie haben ein paar Optionen, wenn.

Die erste option ist die Verwendung der C++ - "export" - Schlüsselwort.Das problem mit diesem scheinbar einfachen Lösung ist, dass niemand unterstützt es.Ist es zu hart für compiler Schriftsteller zu implementieren.

Die zweite option ist zu verwenden eine Dritte Art von Datei, oft getaggt ".ipp", für die Erklärungen.Der trick hier ist, dass es immer noch eine Datei, die muss sein "#enthalten", aber als eine separate Datei, Sie müssen nur schließen Sie Sie in ".cpp" Dateien.Ich habe gefunden, mein linker mag es nicht, wenn ich #include ein ".ipp" in mehr als einer ".cpp" - Datei in einem einzigen Programm, so Sie nicht haben, um wählen Sie eine der includer.

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