В C ++ может ли класс с константным членом данных не иметь оператора присваивания копии? - PullRequest
2 голосов
/ 05 марта 2020

Я разрабатываю класс, который должен иметь элемент данных const с именем K. Я также хочу, чтобы этот класс имел оператор присваивания копии, но компилятор, по-видимому, неявно удаляет оператор присваивания копии из любого класса с постоянными членами-данными. Этот код иллюстрирует существенную проблему:

class A
{
    private:
       const int K;
    public:
       A(int k) : K(k) {} // constructor
       A() = delete; // delete default constructor, since we have to set K at initialization

       A & operator=(A const & in) { K = in.K; } // copy assignment operator that generates the error below
}

Вот ошибка, которую он генерирует:

constructor.cpp:13:35: error: cannot assign to non-static data member 'K' with const- 
qualified type 'const int'
            A & operator=(A const & in) { K = in.K; }
                                          ~ ^
constructor.cpp:6:13: note: non-static data member 'K' declared const here
            const int K;
            ~~~~~~~~~~^
1 error generated.

Я думаю, я понимаю, почему компилятор делает это; экземпляр класса, в который я хочу скопировать, должен существовать до того, как его можно будет скопировать, и я не могу присвоить K в этом целевом экземпляре, если он const, как я пытаюсь сделать выше.

Правильно ли я понимаю эту проблему? И если так, есть ли способ обойти эту проблему? То есть я могу определить конструктор копирования для своего класса и при этом обеспечить защиту K const-like?

1 Ответ

3 голосов
/ 05 марта 2020

В C ++ класс с элементом данных const может иметь конструктор копирования.

#include <iostream>

class A
{
private:
    const int k_;
public:
    A(int k) : k_(k) {}
    A() = delete;
    A(const A& other) : k_(other.k_) {}

    int get_k() const { return k_; }
};

int main(int argc, char** argv)
{
    A a1(5);
    A a2(a1);

    std::cout << "a1.k_ = " << a1.get_k() << "\n";
    std::cout << "a2.k_ = " << a2.get_k() << "\n";
}

Вывод:

a1.k_ = 5
a2.k_ = 5

В C ++ класс с элементом данных const может не использовать оператор присваивания по умолчанию.

class A
{
private:
    const int k_;
public:
    A(int k) : k_(k) {}
    A() = delete;
    A(const A& other) : k_(other.k_) {}

    int get_k() const { return k_; }
};

int main(int argc, char** argv)
{
    A a1(5);
    A a2(0);

    a2 = a1;
}

Возвращает ошибку времени компиляции:

const_copy_constructor.cpp: In function ‘int main(int, char**)’:
const_copy_constructor.cpp:18:10: error: use of deleted function ‘A& A::operator=(const A&)’
   18 |     a2 = a1;
      |          ^~
const_copy_constructor.cpp:1:7: note: ‘A& A::operator=(const A&)’ is implicitly deleted because the default definition would be ill-formed:
    1 | class A
      |       ^
const_copy_constructor.cpp:1:7: error: non-static const member ‘const int A::k_’, can’t use default assignment operator

В C ++ класс с элементом данных const может использовать оператор присваивания не по умолчанию, если вы не пытаетесь изменить элемент данных const, но лучше думать долго и усердно о том, что значит использовать этот оператор присваивания, если один из базовых элементов не может быть изменен.

class A
{
private:
    const int k_;
public:
    A(int k) : k_(k) {}
    A() = delete;
    A(const A& other) : k_(other.k_) {}

    A& operator=(A const& other)
    {
        // do nothing
        return *this;
    }

    int get_k() const { return k_; }
};

int main(int argc, char** argv)
{
    A a1(5);
    A a2(0);

    a2 = a1;
}

Не выдает ошибок времени компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...