在某些C ++代码中,我遇到编译时错误,似乎可能表明我正在尝试重新安装引用。但我确信我不会尝试重新安排参考。我不明白错误的原因。也许我很傻,而且遗漏了一些明显的东西。或许这个问题反映了我不太了解的C ++模板编程的深层原理。无论哪种方式,我希望你们中的一些人可以提供帮助。这是代码:
// p.cpp - slimmed down demonstration of error in prop.cpp
template<class T>
class Property {
protected:
T& value;
public:
explicit Property(T& a) : value(a) { }
// default "copy" setter
virtual Property<T>& operator=(T a) { value = a; return *this; }
// default "copy" getter
virtual operator T() const { return value; }
template<class U> // must invoke U virtual getter and T virtual setter
Property<T>& operator=(const Property<U>& newval)
{ return (*this = U(newval)); }
/* // uncommenting this eliminates the error
Property<T>& operator=(const Property<T>& newval)
{ return (*this = T(newval)); }
/**/
};
int main()
{
//* // this code produces the error
{
int i_ = 10, j_;
Property<int> i (i_), j (j_);
j = i;
}
/**/
/* // this code does NOT produce the error
{
int i_ = 10;
long j_;
Property<int> i (i_);
Property<long> j (j_);
j = i;
}
/**/
return 0;
}
当我用gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
使用命令g++ -o p p.cpp
编译它时,我得到了这个输出:
p.cpp: In member function ‘Property<int>& Property<int>::operator=(const Property<int>&)’:
p.cpp:4:7: error: non-static reference member ‘int& Property<int>::value’, can’t use default assignment operator
p.cpp: In function ‘int main()’:
p.cpp:33:13: note: synthesized method ‘Property<int>& Property<int>::operator=(const Property<int>&)’ first required here
在您告诉我我正在尝试重新设置参考之前,请记住:
取消注释Property::operator=
的定义,它在右侧显式采用与左侧构造类型相同的构造类型,从而消除了错误。因此问题本身并不是Property<int>::value
正在通过*this
访问。
独立地,如main()
所示,operator=
类模板中的Property
方法模板被实例化,并且当右侧的值的数据类型正常工作时=
的{{1}}与=
左侧的数据类型不同。
value
是一个参考,但使用=
为其分配值没有任何问题,至少在一般情况下如此。它不是const
。所以一旦它被实例化(通过Property
唯一的构造函数中的初始化列表保证),为它赋值不会尝试重置它,而是为内存位置分配一个新值。它指的是。
我将提供更大的文件prop.cpp
,其中包含Property
个成员函数的每个单元测试(成功),如果需要。
您可能会注意到此代码是尝试(部分)在C ++中实现“类似函数”(“C#-style”)属性。但是这个问题不是关于它是否真的适合这个真实的C ++项目,也不是关于我选择的模式是否最合适。我可能稍后会就此提出单独的问题。如果你想评论或批评我的方法,我我感兴趣。 我只是要求你不要在这里做,因为它会分散这个问题更具体的目的。相反,你可以发布你自己的问题,可能有你自己的答案,并发表一个简短的评论这里链接到你的新问题。
答案 0 :(得分:3)
正如编译器所说,不能使用编译器生成的赋值运算符来分配非静态引用。需要用户定义的复制赋值运算符。
您的用户定义的赋值运算符执行value
引用的对象的赋值,首先调用operator T()
以获取T
类型的临时值,然后调用Property<T>& operator=(T a)
执行value = a
,用从转换运算符获得的值替换引用的对象。
如果您的班级没有任何内容,您的operator =等同于
// uncommenting this eliminates the error
Property<T>& operator=(const Property<T>& newval)
{
// return (*this = T(newval)); // convert to T, then assign
value = newval.value; // assign the referenced object
return *this;
}
答案 1 :(得分:0)
第二种情况似乎更清楚:使用了用户提供的赋值运算符。
{ U u = U(newval); // extract a value
*this = u; // use the custom assignment operator that takes a
// value as an argument and assigns to a reference
}
第一种情况不同:未选择用户定义的赋值运算符,编译器尝试合成它。这对于非静态引用是不可能的,因此程序是不正确的。