非静态参考成员'int&amp; Property <int> :: value',不能使用默认赋值运算符</int>

时间:2011-12-25 19:20:32

标签: c++ templates operator-overloading reference

在某些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

在您告诉我我正在尝试重新设置参考之前,请记住:

  1. 取消注释Property::operator=的定义,它在右侧显式采用与左侧构造类型相同的构造类型,从而消除了错误。因此问题本身并不是Property<int>::value正在通过*this访问。

  2. 独立地,如main()所示,operator=类模板中的Property方法模板被实例化,并且当右侧的值的数据类型正常工作时=的{​​{1}}与=左侧的数据类型不同。

  3. value是一个参考,但使用=为其分配值没有任何问题,至少在一般情况下如此。它不是const。所以一旦它被实例化(通过Property唯一的构造函数中的初始化列表保证),为它赋值不会尝试重置它,而是为内存位置分配一个新值。它指的是。

  4. 我将提供更大的文件prop.cpp,其中包含Property个成员函数的每个单元测试(成功),如果需要

    您可能会注意到此代码是尝试(部分)在C ++中实现“类似函数”(“C#-style”)属性。但是这个问题不是关于它是否真的适合这个真实的C ++项目,也不是关于我选择的模式是否最合适。我可能稍后会就此提出单独的问题。如果你想评论或批评我的方法,我感兴趣。 我只是要求你不要在这里做,因为它会分散这个问题更具体的目的。相反,你可以发布你自己的问题,可能有你自己的答案,并发表一个简短的评论这里链接到你的新问题。

2 个答案:

答案 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
}

第一种情况不同:未选择用户定义的赋值运算符,编译器尝试合成它。这对于非静态引用是不可能的,因此程序是不正确的。