const перед параметром vs const после имени функции c ++

86

Какая разница между чем-то вроде этого

friend Circle copy(const Circle &);

и что-то вроде этого

friend Circle copy(Circle&) const;

Я знаю const после того, как функция используется, чтобы сообщить компилятору, что эта функция не будет пытаться изменить объект, для которого она вызывается, а как насчет другого?

джазибаз
источник
6
что вы не измените параметр - это другой
Чад

Ответы:

194

Первая форма означает, что Circleобъект (состояние), привязанный к ссылке, которая является параметром copy()функции, не будет изменен copy()посредством этой ссылки. Ссылка является ссылкой на const, поэтому Circleчерез эту ссылку будет невозможно вызывать функции-члены , которые сами не квалифицируются как const.

Вторая форма, с другой стороны, является незаконной: только функции-члены могут быть constквалифицированы (в то время как то, что вы объявляете, является глобальной friendфункцией).

Когда constквалифицирует функцию-член, квалификация относится к неявному thisаргументу. Другими словами, этой функции не будет разрешено изменять состояние объекта, для которого она вызывается (объект, на который указывает неявный thisуказатель) - за исключением mutableобъектов, но это уже другая история.

Чтобы сказать это с помощью кода:

struct X
{
    void foo() const // <== The implicit "this" pointer is const-qualified!
    {
        _x = 42; // ERROR! The "this" pointer is implicitly const
        _y = 42; // OK (_y is mutable)
    }

    void bar(X& obj) const // <== The implicit "this" pointer is const-qualified!
    {
        obj._x = 42; // OK! obj is a reference to non-const
        _x = 42; // ERROR! The "this" pointer is implicitly const
    }

    void bar(X const& obj) // <== The implicit "this" pointer is NOT const-qualified!
    {
        obj._x = 42; // ERROR! obj is a reference to const
        obj._y = 42; // OK! obj is a reference to const, but _y is mutable
        _x = 42; // OK! The "this" pointer is implicitly non-const
    }

    int _x;
    mutable int _y;
};
Энди Проул
источник
11
Хеллува ответ! Спасибо!
SexyBeast
1
Итак, во втором случае, если у меня есть constобъект objкласса X, и я называю его « bar()вроде» obj.bar(obj), что должно произойти и почему? Не должно произойти obj._x = 42сбоя, поскольку objэто объявлено constв вызывающей программе?
SexyBeast
1
Как насчет случая, когда вы заставляете последнюю функцию bar ( void bar(X const& obj) {...}) выглядеть так? void bar(const X& obj) {...}, перенос constключевого слова в это место меняет что-нибудь? Если да, не могли бы вы добавить и этот пример?
Габриэль Стейплс
1
@GabrielStaples Они такие же; constприменяется к тому, что находится слева, или к тому, что находится справа, если слева нет ничего. В вашем случае вы увидите, что для обеих версий constприменяется X.
Андреас Флёйт
69

У методов класса C ++ есть неявный thisпараметр, который стоит перед всеми явными. Итак, функция, объявленная внутри класса, выглядит так:

class C {
  void f(int x);

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

  void f(C* this, int x);

Теперь, если вы объявите это так:

  void f(int x) const;

Вы как будто написали это:

  void f(const C* this, int x);

То есть завершение constделает thisпараметр константным, что означает, что вы можете вызывать метод для константных объектов типа класса и что метод не может изменять объект, для которого он был вызван (по крайней мере, не через обычные каналы).

Джон Цвинк
источник
2
Совершенно правильный, однако он не отвечает на вопрос, который на самом деле относится не к методу класса, а к функции друга.
mah
5
Да, я решил проигнорировать эту friendчасть, потому что я думаю, что она на самом деле не имеет отношения к реальному вопросу ОП (или к тому, чем станет настоящий вопрос, когда все проблемы обнаружатся). Быть по сему.
Джон Цвинк
Я думаю, что утверждение «вы можете вызывать метод для константных объектов типа класса» немного вводит в заблуждение, потому что вы можете вызывать константный метод для константных или неконстантных объектов, тогда как неконстантные функции могут вызываться только неконстантными объектами. в остальном это мой любимый ответ
csguy
8
Circle copy(Circle&) const;

делает constсаму функцию . Это можно использовать только для функций-членов класса / структуры.

Создание функции-члена constозначает, что

  • он не может вызывать какие-либо неконстантные функции-члены
  • Это не может изменять никакие переменные-члены.
  • он может быть вызван constобъектом ( constобъекты могут только вызыватьconst функции). Неконстантные объекты также могут вызывать constфункцию.
  • Это должна быть функция-член класса Circle ».

А теперь рассмотрим следующий:

Circle copy(const Circle &);

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

ПРИМЕЧАНИЕ. Можно перегрузить функцию таким образом, чтобы у нее была constи неконстантная версия одной и той же функции.

Вакар
источник
7

Давайте устраним всю путаницу, связанную с const


constпроизошло от постоянного означает, что что-то не изменяемое, но читаемое.

  1. если мы уточним нашу переменную constключевым словом, мы не сможем изменить ее позже.
    например, переменная const должна быть инициализирована при ее объявлении.
    constint var =25;
    var =50; // gives error

  2. если мы рассматриваем наш переменный указатель с после того, как мы не можем изменить сам указатель , но содержание указателя изменчиво . например // ноconst *

    int *const ptr = new int;
    ptr = new int; //gives error

    *ptr=5445; //allowed

  3. если мы квалифицируем нашу переменную-указатель с помощью before, мы можем изменить сам указатель, но содержимое указателя изменить нельзя . например // ноconst *

    intconst* ptr = new int(85);
    //or
    constint * ptr = new int(85);
    ptr = new int; // allowed

    *ptr=5445; // gives error

  4. указатель и содержимое как постоянные,
    например
    intconst*constptr = new int(85);
    //or
    constint *constptr = new int(85);
    ptr = new int; // not allowed
    *ptr=5445; // not allowed


  1. Circle copy(const Circle &);
    здесь const Circle означает, что значение Circle доступно только для чтения, если мы попытаемся изменить значение Circle внутри функции, это даст ошибку.
  2. friend Circle copy(Circle&) const;
    Этот тип функции не предназначен для переменных, не являющихся членами. Он используется для класса или структуры. Здесь вся функция квалифицируется ключевым словом const, что означает, что мы не можем изменить переменную-член объекта . например
    class A{ public :
              int  var;
              void fun1()
                    { var = 50; // allowed
                    } 
              void fun2()const
                       { var=50; //not allowed
                       }
           }; 
Рамеш Чоудхари
источник
4

Один относится к параметру, другой - к функции.

Circle copy(const Circle &);

Это означает, что переданный параметр нельзя изменить в функции

Circle copy(Circle&) const;

constКвалифицированный функция используется для функций - членов и средств вы не можете изменить элементы данных самого объекта. Пример, который вы опубликовали, был бессмысленным.

Читать справа налево

Если мы перепишем первую функцию как Circle copy(Circle const&);, что означает то же самое, станет ясно, что чтение справа налево становится полезным. copy- это функция, которая принимает constссылку на Circleобъект и возвращает Circleобъект по ссылке.

Алекс Чемберлен
источник
0

friend Circle copy(const Circle &);// относится к постоянному параметру функции. не могу изменить значение, хранящееся в параметре.

Необходимо удалить друга в вашем примере. Копия круга (Круг &) const; // не можем изменить это значение понитера, названное постоянной функцией-членом

шивакумар
источник
-1
friend Circle copy(const Circle &);

Значение параметра не будет изменено во время вызовов функции.

friend Circle copy(const Circle &)const ; 

Функция является аксессором, который не изменяет никаких значений членов класса. В основном, есть типы функций: аксессоры и мутаторы. Аксессор: проверяет, но не изменяет состояние своего объекта.

Сэм
источник