C ++ проблема константности - PullRequest
1 голос
/ 07 марта 2011

У меня проблема с тем, чтобы сделать членов класса постоянными или нет.Позвольте мне привести пример.

#include <iostream>
class ValueClass
{
    int ival;
public:
    void set(int i) {ival = i;}
    int get() {return ival;}
};

class XXX;

class ABC
{
    ValueClass vc;  
public:
    int getval() const {return vc.get() ;}  
friend class XXX;
};

class XXX
{
    std::vector<ABC> abclist;
    void Invalidate()
    {
    // Iterates through abclist and modifies ValueClass members.
    // e.g. abclist[i].vc.set(i);
    }
};

class QWE
{
    const ABC & abc; 
public:
    QWE(const ABC & abc_): abc(abc_) { }
    const ABC & getABC() { return abc; } 
};

int main()
{
    ABC abc;
    QWE qwe(abc);

    std::cout << qwe.getABC().getval()  << "\n"; // Compiler error
}

Мой класс ABC содержит экземпляр ValueClass, который отвечает за получение и получение значения для int.Также в классе QWE есть член ABC, и мне нужно получить этого члена.Мне сказали, что возвращение abc как неконстантного - очень плохая практика.Но тут возникает проблема: я не могу использовать неконстантную vc в функции const int getval() и просто не могу сделать ее const, потому что в другом потоке вызывается XXX::Invalidate().Эта функция изменяет данные в ValueClass относительно некоторых входящих данных.
Очевидно, что с моим дизайном что-то не так, я не могу винить язык C ++.Как я могу решить эту проблему?

Ответы [ 3 ]

3 голосов
/ 07 марта 2011

Make get () const в ValueClass

  class ValueClass
  {
      int ival;
    public:
      void set(int i) {ival = i;}
      int get() const {return ival;} // make get const
  };

Вероятно, следует сделать то же самое для getABC

  const ABC & getABC() const { return abc; } 

Это означает, что этот метод не изменяет объект, для которого он вызывается.

1 голос
/ 07 марта 2011

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

Однако есть еще одна проблема с написанным кодом: его очень легко использовать неправильно и случайно потерять время жизни вашего объекта. Подумайте, не объявили ли вы qwe в main() как:

QWE qwe(ABC());

ABC() создает временный объект ABC и передает его конструктору QWE. Поскольку параметр конструктора abc_ является const ABC&, он будет привязан к этому временному объекту. Затем вы привязываете ссылку на элемент abc к временному объекту через инициализатор abc(abc_). Затем конструктор возвращает.

После возврата конструктора временный объект ABC уничтожается, а qwe.abc является висячей ссылкой: он больше не ссылается на объект.

Если класс собирается повесить на ссылку, которую вы передаете ему, вы должны предпочесть использовать указатель для типа параметра: таким образом, более ясно, что вам нужно беспокоиться о потенциальных проблемах жизни. Кроме того, члены класса ссылочного типа обычно более беспорядочные, чем они того стоят, поскольку они делают класс не присваиваемым (поскольку сами ссылки не присваиваются).

0 голосов
/ 07 марта 2011
class ValueClass
{
    ...
    int get() const {return ival;}
};

class QWE
{
    ...
    const ABC & getABC() const { return abc; } 
};

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

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