12

次のように Cell という名前のテンプレート クラスがあります。

template<class T>class Cell
{
    string header, T data;
}

ここで、Row という名前の別のクラスが必要です。Row には Cells という名前のベクターがあり、Cell と Cell 型の要素の両方をそのベクターに追加できます。出来ますか?

もしそうなら、どうすればそれを行うことができますか? 前もって感謝します。

4

4 に答える 4

24

あなたが提供した追加の詳細では、最初の 2 つの回答は機能しません。必要なのは、セルのバリアントと呼ばれる型であり、それらのベクトルを持つことができます。例えば:-

enum CellType
{
  Int,
  Float,
  // etc
};

class Cell
{
  CellType type;
  union
  {
    int i;
    float f;
    // etc
  };
};

class Vector
{
  vector <Cell> cells;
};

ただし、これを維持するには多くのコードが必要なため、新しい型を追加するのは面倒です。代わりに、共通の基本クラスでセル テンプレートを使用できます。

class ICell
{
  // list of cell methods
};

template <class T>
class Cell : public ICell
{
  T data;
  // implementation of cell methods
};

class Vector
{
  vector <ICell *> cells;
};

新しいセル型を追加するために最初に更新するコードが少ないため、これはうまく機能する可能性がありますが、セル ベクトルでポインター型を使用する必要があります。セルを値で格納した場合、オブジェクトのスライスvector <ICell>によりデータが失われます。

于 2013-04-25T09:26:37.997 に答える
12

これがC++ では不可能であるが、Java/Python では可能である理由は次のとおりです。C++ ベクトルでは、STL コンテナーのストレージ (vector::data() によって返される) には、すべてのオブジェクトのインスタンス化が順次パックされて含まれます。各要素は同じサイズでなければなりません。これにより、アドレス指定が迅速かつ便利になります。したがって、テンプレート クラス A を定義するとします。

template <class T>
class A{
  int id;
  T obj;
};

そのサイズは、テンプレート変数「T obj」に依存します。異なるテンプレート タイプ T の同じクラス A をプッシュすると、ベクトル内の各要素のサイズが異なるため、これは不可能です。唯一の方法は、基本クラスの shared_ptr または unique_ptr のベクトルを使用することです。C++11 と Boost では、shared_ptr と unique_ptr の両方がサポートされています。各派生クラス要素は、異なるテンプレート タイプを持つことができます。このように、基本クラスのポインタのデストラクタが呼び出されると、派生クラスのデストラクタが呼び出されます。例えば、

#include <memory>
#include <vector>
#include <iostream>
#include <string>

using namespace std;

class A{};

template <class T>
class AImpl : public A{
public:
    T obj;
    AImpl(T _obj):obj(_obj){}
    ~AImpl(){
        cout << "Deleting " << obj << endl;
    }
};

int main(int argc, char** argv)
{
    AImpl <string>* a1 = new AImpl <string> ("string1234");
    AImpl <int>* a2 = new AImpl <int> (1234);
    AImpl <double>* a3 = new AImpl <double> (1.234);
    vector <shared_ptr<A>> As;
    As.push_back(shared_ptr<A>(a1));
    As.push_back(shared_ptr<A>(a2));
    As.push_back(shared_ptr<A>(a3));
}

C++11 を有効にするには、必ず -std=c++11 を指定してコンパイルしてください。

出力:

Deleting string1234
Deleting 1234
Deleting 1.234

そして、あなたはあなたが望むものを手に入れます!:)

Java/Python では、すべてのクラス オブジェクト変数は実際にはポインターです。したがって、A の Java 配列または A の Python リストは、A のポインターの C++ 配列と同等です。したがって、明示的に作成しなくても本質的に同じ機能が得られます。 shared_ptrs.

于 2016-04-13T03:43:33.867 に答える
6

他の答えは良いですが、おそらくあなたが望んでいた:

template<class T>
class Row
{
private:
    class Cell {
        string header;
        T data;
    }

    std::vector<Cell> cells;
    ...
}
于 2013-04-25T09:14:11.167 に答える
4

このようなもの?

template<class T>
class Row
{
private:
   std::vector<Cell<T> > cells;
};

わかりました、この答えは間違っています。

したがって、1 つのvector異なるセルに格納する場合は、動的な型識別を使用する必要があります (1 つの基本クラスを使用して、それへのポインタをベクトルに格納し、仮想関数のみを使用し、すべての派生クラスでオーバーライドされます。のようなものを保存し、挿入された要素ごとにboost::anyいくつかを保存して、それらを実際の型にキャストして操作することができます)。type-identification

于 2013-04-25T09:09:37.050 に答える