Оператор присваивания по умолчанию во внутреннем классе со ссылочными членами

StackOverflow https://stackoverflow.com/questions/1832704

Вопрос

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

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, но это только скрывает проблему (я до сих пор не понимаю, почему я не могу этого сделать).

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

Это было полезно?

Решение

Эта проблема не имеет ничего общего с внутренними классами.В 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;
}

Другие советы

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top