1

シリアル化用のデータを準備するために使用されるクラスのセットがあります。cBaseそれらはすべて、質問に関連するものを何も保持していない基本クラスから派生しています。

派生クラスには次のものがあります。

class cValue: public cBase
{
public:
    cValue(){}
    template< class T > void set( const T & value ){ data_ = value; }

protected:
    QVariant data_;
};

これは、文字列や数値などの単純な値を保持するためのクラスです。そして、これがオブジェクトを表すクラスです(基本的には「名前と値」のペアを保持できるものです。

class cObject: public cBase
{
public:
    cObject(){}

    void addAttribure( const QString & name, cBase * value )
    {
        if( attributes_.contains( name ) )
            delete attributes_[name];
        attributes_[name] = value;
    }

    template< class T > void addAttribure( const QString & name, const T & value )
    {
        cValue * tmp = new cValue();
        tmp->set( value );
        addAttribure( name, tmp );
    }
protected:
    QMap< QString, cBase * > attributes_;
};

これの目的は、作成済みのオブジェクトaddAttribute(someName, someObject);と生の値の両方で属性を追加できるようにすることです。addAttribute("name", 42);

さて、このコードはそのままコンパイルされます。ただし、次のようなオブジェクトを作成しようとすると、次のようになります。

cValue *tmp = new cValue();
tmp->set( 42 );
cObject obj;
obj.addAttribure("The Answer", tmp);

次のエラーが発生します。

/usr/include/qt4/QtCore/qvariant.h:429:12: error: 'QVariant::QVariant(void*)' is private
../../source/private/../include/MyClasses.h:36:51: error: within this context

エラーは、cValueset()関数が宣言されている行に表示されます。ここで、のテンプレートバージョンを削除し、addAttribute()その関数からまったく同じコードをメインに配置すると、次のようになります。

cObject obj;
cValue * tmp = new cValue();
tmp->set( 42 );
obj.addAttribure( "The Answer", tmp );

それはうまくいきます。addAttribute()と関数の両方がテンプレート化されているという事実と関係があると思いますが、set()この問題を修正する方法、または少なくとも回避策を作成する方法を理解できていません。

:可能であれば、クラス自体をテンプレート化せず、関数のみを作成したいと思います

4

4 に答える 4

2

問題、およびキャストを使用した修正が機能する理由は、シグネチャのパラメーターの型を正確に使用して呼び出したときに、コンパイラーがテンプレート化されていない関数のみを選択することです。この場合、 ではなく を使用してcBase*cObject*ます。確かに、後者は前者に自動的に変換できますが、コンパイラは、テンプレートをインスタンス化してパラメーターと完全に一致する関数を作成できることを認識し、それを選択します。

キャストと一緒に行くことができます:

addAttribure( name, static_cast<cBase *>(tmp) );

または、キャストを回避するために基本クラスのポインターを直接使用することもできます。

cBase* pBase = tmp;
addAttribure( name, pBase );
于 2012-09-06T07:18:26.353 に答える
0

タイプの識別に問題があるのか​​もしれません。QTでも同様の問題がありましたが、少し前です。多分あなたは試してみるべきです

template< class T > void set( const T & value )
{   
  data_ = QVariant::fromValue( value ); 
  // or data_.setValue( value )
}
于 2012-09-05T14:26:28.487 に答える
0

問題は、が から派生しているためaddAttribure(const QString& name, cBase* value)、 を使用するときにコンパイラが呼び出すことを期待していることです。ただし、それらは完全に一致しないため、コンパイラは代わりに呼び出します。cValuecValuecBaseaddAttribure<cValue*>(const QString& name, const cValue* value)

そのため、(コメントに記載されているように)呼び出しが機能しaddAttribure(name, static_cast<cBase*>(tmp))ました。

于 2012-09-06T07:04:45.347 に答える