0

この新しいクラスを作成しました:

//------------------------------------------------------------------------------
#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
//------------------------------------------------------------------------------

クラスの定義:

//------------------------------------------------------------------------------
#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_;

}

ここで問題となるのは、コードで別のクラスの静的メンバーとして使用しようとすると、次のようになります。

// VehicleManager.h
#ifndef MULTITHREADEDVECTOR_H
#define MULTITHREADEDVECTOR_H

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

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

#endif

次に内部:VehicleManager.cpp

#include "VehicleManager.h"

MultithreadedVector<Vehicle> VehicleManager::vehicles_;

void VehicleManager::Method() {

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

}

しかし、それはコンパイルされません:(、私は毎回このエラーメッセージを受け取ります:

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

特に、VehicleManager.cppのグローバルスコープで静的クラスメンバーを定義した理由はよくわかりません。

PS:私はCode::Blocksを使用しています。

ありがとう !

4

8 に答える 8

5

これは、クラステンプレートの実装を盲目的にcppファイルに移動したときに発生することです。

これを機能させるには、クラステンプレートをインスタンス化するTのタイプを正確に把握し、それらをcppファイルで指定する必要があります。

この場合、これをcppファイルに入れます。

template class MultithreadedVector<Vehicle>;

cppファイルはそのことを知っている必要があることに注意してくださいVehicle

于 2009-06-16T13:14:38.713 に答える
4

ほとんどのC++コンパイラでは、テンプレート宣言とテンプレート定義を分離できません。テンプレートクラスの完全な定義を.hファイルと.cppファイルに分割するのではなく、単一の.hファイルに入れる必要があります。

于 2009-06-16T13:12:27.050 に答える
2

テンプレート実装の完全なコードは、テンプレートの使用を確認した時点でコンパイラーに表示される必要があります。これにより、テンプレートをインスタンス化し、後でリンクできるオブジェクトコードにコンパイルできます。

テンプレートが宣言されているのと同じヘッダーファイルでテンプレートコードを定義します。

于 2009-06-16T13:11:23.120 に答える
2

テンプレートの使い方には2つのケースがあると思います

  1. 適合する型の任意のセットに汎用コードを提供する
  2. 型の固定セットに汎用コードを提供する

2 番目の場合、テンプレートをヘッダーに配置する必要はありません。テンプレートがどのタイプで使用されているかが事前に正確にわかっているためです。リンカー エラーなしで、クラス テンプレートのメンバー関数、または別の翻訳単位の関数テンプレートを適切に定義できます。一部の人々は、これは不可能であると他の人に教え続け、これによって問題を混乱させます.

しかし、宣言と定義を異なる翻訳単位に分離するかどうかは、これら2つのケースに依存すると思います。

  • ケース 1 を使用する場合は、常にヘッダーに定義が必要です ( などの特別な名前のファイルに含まれているかどうかに関係なく.ipp) .tcc。この場合でも、定義を宣言から分離することをサポートする C++ フロントエンドを 1 つだけ知っています。これは、intel および comeau コンパイラで使用され、export. そのキーワードは一部の人にとっては誤機能と見なされており、ほとんどのコンパイラはそれを実装していません。

  • ケース 2 を使用する場合は、定義をヘッダーに配置するのは適切ではありません。そうする理由がないからです。型の固定セットに必要な関数とクラスを明示的にインスタンス化するだけです。この 2 番目のシナリオでは、テンプレートを使用して、重複する可能性のあるコードを維持する負担を軽減し、場合によっては一部の型に特別な動作を導入するオプションを開きます。

あなたのシナリオは明らかにケース 1 の状況であるため、定義をヘッダーに入れる必要があります。

于 2009-06-16T23:27:10.257 に答える
1

VehicleManager.hにコピーアンドペーストエラーがあるようです。

#ifndef MULTITHREADEDVECTOR_H
#define MULTITHREADEDVECTOR_H

これにより、クラスFooが定義されているヘッダーファイルをインクルードできなくなります。

于 2009-06-16T13:12:54.350 に答える
1

ほとんどの場合、cppファイルにテンプレートの実装を書き込むことはできません。テンプレートの実装をヘッダーファイルに移動して、コンパイラが適切にインスタンス化できるようにします。

于 2009-06-16T13:13:28.187 に答える
1

他の答えとは別に:

あなたも守らなければなりませんget_container()。このメソッドは基本的にcontainer_要素をコピーするため、保護する必要があります。

template<class T>
vector<T> MultithreadedVector<T>::get_container() 
{
    return container_;
}
于 2009-06-16T13:15:34.233 に答える
1

テンプレートはある意味で、高度で特殊な種類のマクロのようなものです。やろうとしているように見えるように、実際にテンプレート定義を個別にコンパイルすることはできません。

ほとんどの人にとって、これは、テプレート定義を宣言から分離することさえ気にしないことを意味します。これをさらに一歩進めて、テンプレート以外の定義と宣言を分離することを拒否する同僚が 1 人います。

宣言からテンプレートの定義を入れたい場合は、いくつかのオプションがあります。

最初のオプションは、C++ の "export" キーワードを使用することです。この一見単純なソリューションの問題は、誰もそれをサポートしていないことです。コンパイラの作成者が実装するには難しすぎます。

2 番目のオプションは、宣言に「.ipp」とタグ付けされることが多い3 番目のタイプのファイルを使用することです。ここでの秘訣は、「#include」する必要があるファイルであることですが、別のファイルであるため、「.cpp」ファイルに含めるだけで済みます。1 つのプログラムで複数の「.cpp」ファイルに「.ipp」を #include すると、リンカーがそれを好まないことがわかったので、1 つをインクルーダーとして選択する必要があります。

于 2009-06-16T13:55:57.787 に答える