Как изменить частные члены, которые являются постоянными? - PullRequest
0 голосов
/ 30 июня 2011

Я знаю, это звучит странно, но терпите меня.

У меня есть собственный класс, в котором есть несколько больших объектов, которые нужно возвращать по ссылке, чтобы избежать копирования.

Мой класс выглядит примерно так:

    class csv_File {
    public:
      csv_File(std::string); //constructor
      std::string const& access(int,int) const;
      void modify_element(int column,int row ,std::string value) {
        storage.at(row).at(column)=value;
    }

    private:
      mutable std::vector < std::vector<std::string> > storage;

    };

Код доступа:

    string const& csv_File::access(int column,int row) const {
    return storage.at(row).at(column);
    }

Когда я пытаюсь скомпилировать это, я получаю сообщение об ошибке, как он хочет

csv_File::modify_element(int column,int row ,std::string value) const {}

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

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

1 Ответ

1 голос
/ 30 июня 2011

После исправления вашей программы и подсказки @ user763305, я полагаю, у вас есть что-то вроде этого (примечание: эта программа компилируется, но при запуске вызывает неопределенное поведение, поскольку вектор storage остается пустым):

#include <string>
#include <vector>

class csv_File {
public:
  csv_File(std::string) {}
  std::string const& access(int,int) const;
  void modify_element(int column,int row ,std::string value) {
    storage.at(row).at(column)=value;
  }

private:
  mutable std::vector < std::vector<std::string> > storage;

};

std::string const& csv_File::access(int column,int row) const {
  return storage.at(row).at(column);
}

const csv_File& Factory() { static csv_File foo("foo.txt"); return foo; }
int main(){
    const csv_File& f(Factory());
    f.modify_element(1, 2, "hello");
}

и вы получаете сообщение об ошибке, подобное этому:

cs.cc: In function ‘int main()’:
cs.cc:24: error: passing ‘const csv_File’ as ‘this’ argument of ‘void csv_File::modify_element(int, int, std::string)’ discards qualifiers

Итак, у вас есть объект const и вы пытаетесь вызвать modify_element для него.Логично, что это ошибка - вы не можете изменять const объекты!

У вас есть, как я вижу, два варианта исправления.Либо вы можете объявить объект vector mutable и метод modify_element const, либо изменить фабрику объектов, чтобы она возвращала неконстантные ссылки.

Решение 1:

...
  void modify_element(int column,int row ,std::string value) const {
    storage.at(row).at(column)=value;
  }
...

Решение 2:

...
const csv_File& Factory() { static csv_File foo("foo.txt"); return foo; }
csv_File& RW_Factory() { static csv_File foo("foo.txt"); return foo; }
...
  const csv_File& f(RW_Factory());
...

РЕДАКТИРОВАТЬ И, да, если вы ранее возвращали ссылку на string в своем vector, и впоследствии вы присваиваете этому значению string новое значение, как вmodify_element, тогда предыдущая ссылка будет отражать новое значение.

Обратите внимание, что предыдущая ссылка будет недействительной, если вы уничтожите вектор, сотрете элемент vector или сделаете что-нибудь, чтобы вызвать vectorвыйти за пределы своей прежней способности.

...