Состояние в операторе = - PullRequest
       3

Состояние в операторе =

0 голосов
/ 27 января 2020

Предположим, у меня есть объект типа B, который содержит объект типа A. И A содержит целое число, которое нельзя изменить. От B A возвращается по неконстантной ссылке (поскольку она содержит несколько полезных методов):

class A {
private:
    int i;
public:
    A(int i) : i(i) {};

    void doSomethingNonConst() {}

    int getInt() {
        return i;
    }
}

class B {
public:
    A& getA();
}

Но есть проблема: я могу сделать что-то вроде следующего: getA() = A(5); Какие из Конечно, изменяется целое число, которое не может быть изменено. Мое решение - сделать что-то с operator=, а именно , чтобы копировать только тогда, когда целевые и исходные целые числа равны , в противном случае выдается исключение:

A& operator=(const A& a) {
    if (a.i == i) {
        //do copy
    } else
        //throw an exception
} 

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

Ответы [ 2 ]

2 голосов
/ 27 января 2020

А содержит целое число, которое нельзя изменить.

Затем либо сделайте это int const:

class A {
private:
    const int i;
...

и / или сделайте A in B const и возвращаем const ссылку ::

class B {
private:
    const A a;
public:
    const A& getA();
}
1 голос
/ 27 января 2020

Хотя вы можете это сделать, это может сбить с толку людей, и вам придется справиться с этим во время выполнения. Часто более желательно получить ошибку во время компиляции и просто полностью запретить «копирование».

В этом случае вы можете сделать целое число const, что предотвратит неявный оператор копирования по умолчанию.

class A {
private:
    const int i;
public:
    A(int i) : i(i) {};

    void doSomethingNonConst() {}

    int getInt() {
        return i;
    }
};
class B {
public:
    B() : a(5) {}
    A &getA() { return a; } // still non-const here
private:
    A a;
};
int main()
{
    B b;
    A otherA(60);
    // Compile error. GCC: use of deleted function 'A& A::operator=(const A&)'
    // 'A& A::operator=(const A&)' is implicitly deleted because the default definition would be ill-formed
    b.getA() = otherA;
}

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

Это можно сделать, удалив операторы по умолчанию A &operator = (const A &) = delete;.

class A {
private:
    int i;
public:
    A(int i) : i(i) {};

    A (const A &) = delete;
    A &operator = (const A &) = delete;

    void doSomethingNonConst() {}

    int getInt() {
        return i;
    }
};
int main()
{
    B b;
    A otherA(60);
    b.getA() = otherA; // Compile error. GCC: use of deleted function 'A& A::operator=(const A&)'
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...