Как отказаться от const в C ++ - PullRequest
2 голосов
/ 26 мая 2010

Это то, что я пытаюсь сделать, и я не могу:

#include <string>
using namespace std;
class A {
public:
  bool has() const { return get().length(); }
  string& get() { /* huge code here */ return s; }
private:
  string s;
};

Я получаю ошибку:

passing ‘const A’ as ‘this’ argument of
‘std::string& A::get()’ discards qualifiers

Я понимаю, в чем проблема, но как я могу это исправить? Мне действительно нужно has(), чтобы быть const. Спасибо.

Ответы [ 5 ]

6 голосов
/ 26 мая 2010

Добавьте вторую перегрузку get():

string const & get() const { return s; }

Это будет вызвано для const типизированного объекта класса A.

На практике я предпочитаю добавлять только const -типовые аксессоры, а затем сохранять модификации полностью внутренними для класса или даже избегать их полностью. Например, это означает наличие метода DoUpdateLabel(){/*do something with s*/} вместо раскрытия внутренних данных. Это имеет приятный побочный эффект: во многих случаях вы можете избежать дублирования методов доступа.

Если вам абсолютно необходимо внести изменения через средства доступа, а также вам не нужна дополнительная const-оболочка, вы можете использовать const_cast<>:

bool has() const { return const_cast<A*>(this)->get().length(); }

Однако, если get() имеет побочные эффекты и has() объявлен const, сомнительно, действительно ли это поведение, которое вы действительно хотите.

2 голосов
/ 26 мая 2010

Я думаю, что ваш вопрос немного расплывчатый.

У вас есть:

bool has() const { return get().length(); }
string& get() { /* huge code here */ return s; }

... и нужно has(), чтобы быть const.

Я могу придумать три способа обойти это, в зависимости от того, что вы на самом деле пытаетесь сделать:

Самым чистым вариантом будет has, чтобы использовать только код const. Если некоторые из ваших /* huge code here */ кодов неконстантны, но фактически не изменяют логическое значение класса (например, вычисление кэшированного внутреннего значения) , рассмотрите возможность использования mutable для задействованных данных .

Если часть /* huge code here */ не является константной по своей природе, рассмотрите возможность преобразования ее в другую функцию и вызова ее отдельно:

using namespace std;
class A {
public:
  bool has() const { return get().length(); }
  const string& get() const {  return s; }
  void computestuff() { /* huge code here */ }
private:
  string s;
};

A  instance;

// old client code:
// string s = instance.get();
//
// new code:
instance.computestuff(); // non-const call
instance.get(); // const call
instance.has(); // const call

В конечном счете, вы также можете отбросить постоянство (но имейте в виду, что необходимость в этом почти всегда является признаком плохого дизайна / необходимости рефакторинга):

class A {
public:
  bool has() const { return const_cast<A*>(this)->get().length(); }
  string& get() { /* huge code here */ return s; }
private:
  string s;
};
2 голосов
/ 26 мая 2010

Довольно обычно иметь версии const и non-const с одинаковыми функциями.

Итак, один из них будет вызван, если ваш объект называется const объектом, а второй - если то же самое произойдет с non-const.

Я должен отметить, что этот метод обычно используется с операторами, но также подходит для текущего случая.


Кроме того, в вашем текущем случае лучший подход может означать использование ТОЛЬКО const метода, подобного

const string& get() const { return s }

и рефакторинг всего вашего другого кода, чтобы он работал со строкой, возвращаемой через постоянную ссылку.

0 голосов
/ 26 мая 2010

Попробуйте это:

const string& get() const { return s; }

Первое const применяется к типу возвращаемого значения метода get (). Тип возвращаемого значения является ссылкой на строку. В целом это константная ссылка на строку, которая гарантирует, что это значение не должно изменяться.

Второй метод const применяется к методу, что делает его методом const.

0 голосов
/ 26 мая 2010
std::string get() const { return s; }

потому что передача строк по значению, как правило, дешево (я не помню, является ли это гарантией), и я не думаю, что вы хотите, чтобы строка, на которую вы смотрите, менялась под вашими ногами, когда А изменяет ее.

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