нестатический ссылочный член int & Property <int>:: value, не может использовать оператор присваивания по умолчанию - PullRequest
0 голосов
/ 25 декабря 2011

В некотором коде 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 создается и отлично работает, когда тип данных значения в правой части = отличается из типа данных слева =.

  3. value является ссылкой, но нет ничего плохого в том, чтобы присвоить ему значение с помощью =, по крайней мере, в целом. Это не const. Поэтому, когда он создается (что гарантировано через список инициализации в единственном конструкторе Property), присвоение ему значения не пытается переустановить его, а вместо этого назначает новое значение в ячейку памяти, к которой оно относится .

Я предоставлю больший файл prop.cpp, который содержит (успешные) модульные тесты для каждой из Property функций-членов, , если требуется .

Вы можете заметить, что этот код является попыткой (частично) реализовать "подобные функции" ("стиль C #") свойства в C ++. Но этот вопрос не о том, действительно ли это уместно делать в реальном C ++ проекте, и не о том, является ли выбранный мной шаблон наиболее подходящим. Возможно, я задам отдельные вопросы об этом позже. Если вы хотите прокомментировать или критиковать мой подход, я заинтересован . Я только прошу, чтобы вы не делали этого здесь, потому что это отвлекло бы внимание от более конкретной цели этого вопроса. Вместо этого, вы можете опубликовать свой вопрос, возможно, с собственным ответом, и опубликовать краткий комментарий здесь ссылка на ваш новый вопрос.

Ответы [ 2 ]

3 голосов
/ 25 декабря 2011

Как сказал компилятор, нестатическая ссылка не может быть назначена с помощью сгенерированного компилятором оператора присваивания.Требуется пользовательский оператор назначения копирования.

Ваш пользовательский оператор назначения выполняет назначение объекту, на который ссылается value, сначала вызвав ваш operator T(), чтобы получить временное значение типа Tа затем ваш Property<T>& operator=(T a) для выполнения value = a, который заменяет ссылочный объект значением, полученным из оператора преобразования.

Если из вашего класса ничего не получено, ваш оператор = эквивалентен

// 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;
    }
0 голосов
/ 25 декабря 2011

Второй случай кажется немного понятнее: используется пользовательский оператор присваивания.

{ 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
}

Первый случай отличается: пользовательский оператор присваивания не выбран, и компилятор пытается его синтезировать. Это не возможно для нестатических ссылок, и, следовательно, программа некорректна.

...