C ++: это действительная постоянная функция-член? - PullRequest
1 голос
/ 22 сентября 2011

В настоящее время я работаю над классом c ++. Цель этого класса - выполнить несколько http-запросов. Вы создаете экземпляр, указывающий

  • URL назначения
  • некоторые другие параметры

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

class HttpRequest
{
   public:
   // omitted constructor, ...
   const std::list<Child> getChildren() {
      // do the http query
      // build a list
      return(list);
   }
}

Список, возвращаемый getChildren, может меняться для каждого вызова - в зависимости от других действий, выполняемых на HTTP-сервере. Каково ваше мнение: как мне объявить метод:

  • const std::list<Child> getChildren();
  • const std::list<Child> getChildren() const;

Он будет компилироваться обоими способами, поскольку getChildren не изменяет HttpRequest.

Спасибо за вашу помощь, Ули

Ответы [ 4 ]

3 голосов
/ 22 сентября 2011
  • const std::list<Child> getChildren();
  • const std::list<Child> getChildren() const;

Компилируется в обоих направлениях, поскольку getChildren не изменяет HttpRequest.

  1. Нет, он не будет компилироваться в обоих направлениях.(Если это так, для чего будет эта разница?) Вторая форма требуется для вызова getChildren() для const HttpRequest объектов (или ссылок или указателей):

    void f(const HttpRequest& req)
    {
       const std::list<Child>& list = req.getChildren(); // requires const
       // ...
    }
    

    Это потребует завершающегоconst.

  2. Верхний уровень const для типа возврата (const std::list<Child>) вообще не имеет значения.Возвращенный объект является значением.Все, что вы можете сделать с ним, это сделать копию или привязать ее к const std::list<Child>& - независимо от того, const или нет.

  3. Скорее всего, вы не хотите копировать такие списки для копирования каждый раз, когда вызывается getChildren(), поэтому вы должны вернуть ссылку :

    const std::list<Child>& getChildren() const;
    

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

  4. Вы можете перегрузить на основепо следу const.Учитывая это, вы можете иметь две версии: одну для изменения списка и одну для получения const ссылки на список:

    const std::list<Child>& getChildren() const;
          std::list<Child>& getChildren();
    

    Я бы не знал, имеет ли это смысл в вашем случае.

2 голосов
/ 22 сентября 2011

Моя первоначальная внутренняя реакция заключается в том, что если трудно решить, мы должны рассмотреть функцию более подробно. Кроме того, поскольку состояние HttpRequest не является мутированным, и поскольку оно может каждый раз возвращать другое значение, возможно, функция вообще не должна быть членом. Кажется, что это может иметь больше смысла как не член, не друг, который использует HttpRequest для выполнения своей работы и возврата значения. Тогда const-семантика ясна.

1 голос
/ 22 сентября 2011

Если вы хотите убедиться, что функция не изменяет состояние объекта HttpRequest, тогда вам нужно std::list<Child> getChildren() const. Нет никакой причины делать std::list константой, если только вы не вернете ссылку.

1 голос
/ 22 сентября 2011

Основное правило - объявить функцию-член равной const, если вы можете. Если getChildren вносит какие-либо изменения, которые, по-видимому, изменяют состояние объекта HttpRequest, к которому он обращен (даже если он фактически не изменяет состояние), возможно, вы должны объявить его неконстантным, чтобы не запутывать людей. Но в противном случае это должно быть const.

Кроме того, я понимаю логику того, почему вы объявляете возвращаемое значение равным const. Я бы все же предложил тебе не делать этого. С C ++ 11 и конструкторами перемещения и тому подобным, на самом деле очень полезно (и более точно), чтобы он был неконстантным.

...