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

错误出现在声明函数cValue的行上。set()现在,如果我删除 的模板版本addAttribute(),并将该函数中完全相同的代码放入我的 main 中:

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

它工作正常。addAttribute()我认为这与 和函数都是模板化的事实有关set(),但我不明白如何解决这个问题,或者至少不明白如何解决这个问题。

注意:如果可能的话,我不想让类本身模板化,只有函数。

4

4 回答 4

2

问题以及使用强制转换进行修复的原因在于,编译器仅在您使用其签名的参数类型调用它时才选择非模板化函数。在这种情况下,您使用的不是 a cBase*,而是 a 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

这可能与此有关:

http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/topic/com.ibm.xlcpp8a.doc/language/ref/keyword_template_qualifier.htm

我隐约记得我自己的成员模板函数在我明确限定它们之前没有编译。

于 2012-09-05T21:50:56.950 回答
0

问题是您期望编译器addAttribure(const QString& name, cBase* value)在使用时调用cValue,因为cValue它是从cBase. 但由于它们不是完全匹配,编译器addAttribure<cValue*>(const QString& name, const cValue* value)改为调用。

这就是为什么(如您的评论中所述)调用addAttribure(name, static_cast<cBase*>(tmp))有效的原因。

于 2012-09-06T07:04:45.347 回答