Оператор присваивания по умолчанию во внутреннем классе со ссылочными элементами - PullRequest
7 голосов
/ 02 декабря 2009

Я столкнулся с проблемой, которую я не понимаю, и я надеялся, что кто-то здесь может дать некоторую информацию. Упрощенный код выглядит следующим образом (исходный код представлял собой пользовательскую реализацию очереди / очереди-итератора):

class B
{
public:
    B() {};
    class C
    {
    public:
        int get();
        C(B&b) : b(b){};
    private:
        B& b;
    };
public:
    C get_c() { return C(*this); }
};

int main()
{
    B b;
    B::C c = b.get_c();


    c = b.get_c();
    return EXIT_SUCCESS;
}

При компиляции выдается следующая ошибка:

foo.cpp: In member function 'B::C& B::C::operator=(const B::C&)':
foo.cpp:46: error: non-static reference member 'B& B::C::b', can't use default assignment operator
foo.cpp: In function 'int main()':
foo.cpp:63: note: synthesized method 'B::C& B::C::operator=(const B::C&)' first required here

Я могу обойти это, используя две отдельные переменные C, поскольку они должны быть независимыми объектами 'C', но это только скрывает проблему (я все еще не понимаю, почему я не могу этого сделать). 1007 *

Я думаю, что причина в том, что ссылка не может быть скопирована, но я не понимаю, почему. Нужно ли предоставлять свой собственный оператор присваивания и конструктор копирования?

Ответы [ 4 ]

13 голосов
/ 02 декабря 2009

Эта проблема не имеет ничего общего с внутренними классами. В C ++ вы просто не можете (пере) назначать ссылки - их нужно инициализировать при определении.

Более простой пример:

class B
{
public:
    B(int& i) : ir(i) {};

    int& ir;
};


int main()
{
    int i;
    B b(i);      // Constructor - OK

    int j;
    B bb = B(j); // Copy constructor - OK

    bb = b;      // Assignment - Error
    return 0;
}
6 голосов
/ 02 декабря 2009

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

3 голосов
/ 02 декабря 2009

На самом деле, есть решение для этого. Вы можете реализовать operator = с точки зрения построения копии , и это сработает :) Это очень эффективный метод для таких случаев. Предполагая, что вы хотите поддержать назначение.

0 голосов
/ 02 декабря 2009

C ++ не имеет "внутренних классов", только вложенные объявления классов. «Внутренние классы» - это Java-изм, который, я думаю, не встречается в других основных языках. В Java внутренние классы являются особыми, потому что они содержат неявную неизменяемую ссылку на объект содержащего типа. Для достижения эквивалента вложенным объявлениям C ++ в Java требуется использование статических внутренних классов; статические внутренние классы не содержат ссылку на объект объявленного типа.

...