2017-01-02 5 views
1

を導出I持って次のシナリオ:Accessのデータはテンプレートクラス

class ScalarField 
{ 
    void* _buffer; //Array for data. 
}; 

と派生クラス:Tだけの基本的なタイプを想定することができ

template <typename T> 
class ScalarFieldT : public ScalarField 
{ 
    ScalarFieldT(int size) 
    { 
     _data = new T[size]; 
     _buffer = _data; 
    } 

    T& get(int index) 
    { 
     return _data[index]; 
    } 

    T* _data; // Typed array for data 
}; 

ていることに注意してくださいそのような浮動小数点、int、doubleなど。

これは非常に古いレガシーコードなので、適切な設計をして適切に調整する柔軟性はあまりありません。必要なことは、ScalarField::_bufferから派生クラスの正しい型キャストを使用してデータにアクセスすることです。このような

何か:

void main() 
{ 
    int n = TOTAL_SIZE; 
    ScalarFieldT<int> typedScalarField(n); 

    ScalarField* scalarField = &typedScalarField; 

    // This is what I need to do: 
    int index = ELEMENT_INDEX;   
    float value = scalarField->method(index); // Get the value from base class correctly converted from int to float, for example.  
} 

ポイントは、私が唯一、基本クラスの抽象化へのアクセス権を持って、ですが、私は別の単純なデータ型は、そのようなフロート、intに変換_bufferから値を取得する必要があり、 ucharなど

あなたは何をお勧めしますか?

ありがとうございます!

+0

あなたは 'int'はその'メイン() 'の例では' float'としてキャストすることにしますか、またはあなたが 'という100%を確保していきますfloat value = scalarField-> get(index); '' ScalarFieldT 'としてインスタンス化されたscalarFieldで呼び出されますか? – Frank

+0

'static_cast'を使用してください。 –

+0

'ScalarField *'があるところで、 '_buffer'が指し示す要素の実際の型を知っていますか?つまり、この特定のインスタンスが基本クラスのサブオブジェクトである 'ScalarFieldT 'の 'T'を知っていますか?それがなければ、あなたは悲しいかなか幸運ではない、私は恐れている。 'ScalarField'だけを見ると、' _buffer'が 'int'の配列や' float'の配列を指しているのかどうかを知ることはできませんが、もちろん配列の実際のビットはこれらの2つのケースでは非常に異なった解釈をしています。 –

答えて

0

フム - 例えば、

だがTは、数値データ型に制限されていると仮定しましょう、おそらく愚かな答えを私に石を投げたが、...しないでくださいint,long,double,floatとし、さらに記憶される最大の積分値が約2^53であると仮定する。したがって、doubleは、精度を損なうことなく他のデータ型を変換できるデータ交換データ型として機能する可能性があります。

virtual double ScalarField::method(int index) = 0を定義すると、実際にタイプTからdoubleにキャストアップされた型付きバリアントでオーバーロードされます。あなたがオブジェクトの値をカプセル化する(例えばカルコゲノフルバレン骨格/クラス値を)許可されていない限り

、仕事ができる「データ交換データ型として、二重使用」を使用して次のコード:あなたが使用することができます

class ScalarField 
{ 
public: 
    void* _buffer; //Array for data. 
    virtual double method(int index) = 0; 
}; 

template <typename T> 
class ScalarFieldT : public ScalarField 
{ 
public: 
    ScalarFieldT(int size) 
    { 
     _data = new T[size]; 
     _buffer = _data; 
    } 

    virtual double method(int index) { return get(index); } 

    T& get(int index) 
    { 
     return _data[index]; 
    } 

    T* _data; // Typed array for data 
}; 
1

methodの戻り値の型としてキャスト演算子のセットを提供する型です。
それは、最小限の作業例を次に示します。

#include<memory> 

class ScalarField { 
protected: 
    struct Value { 
     virtual operator float() const = 0; 
     virtual operator int() const = 0; 
     // ... 
    }; 

public: 
    virtual const Value & method(int i) = 0; 

protected: 
    void* buffer; 
}; 

template <typename T> 
class ScalarFieldT : public ScalarField { 
    struct TValue: Value { 
     TValue(T value): value{value} {} 
     operator float() const override { return float(value); } 
     operator int() const override { return int(value); } 
     // ... 

    private: 
     T value; 
    }; 

public: 
    ScalarFieldT(int size) { 
     data = new T[size]; 
     buffer = data; 
    } 

    T& get(int index) { 
     return data[index]; 
    } 

    const Value & method(int i) { 
    std::make_unique<TValue>(data[i]); 
} 

private: 
    std::unique_ptr<Value> value; 
    T* data; 
}; 

int main() { 
    ScalarFieldT<int> typedScalarField(10); 
    ScalarField* scalarField = &typedScalarField; 
    float f = scalarField->method(2); 
    int i = scalarField->method(5); 
} 
関連する問題