const przed parametrem vs const po nazwie funkcji c ++

86

Jaka jest różnica między czymś takim

friend Circle copy(const Circle &);

i coś takiego

friend Circle copy(Circle&) const;

Wiem, że const po użyciu funkcji, aby powiedzieć kompilatorowi, że ta funkcja nie będzie próbowała zmienić obiektu, do którego jest wywoływana, a co z drugim?

jazzybazz
źródło
6
że nie zmienisz parametru, to druga
Czad,

Odpowiedzi:

194

Pierwsza postać oznacza, że ​​(stan) Circleobiektu związanego z odwołaniem, które jest parametrem copy()funkcji, nie zostanie zmieniony przez copy()to odwołanie. Odwołanie jest odwołaniem do const, więc nie będzie możliwe wywołanie funkcji składowych za Circlepośrednictwem tego odwołania, które same nie są kwalifikowane jako const.

Z drugiej strony, druga forma jest niedozwolona: tylko funkcjeconst składowe mogą być kwalifikowane (podczas gdy to, co deklarujesz, jest friendfunkcją globalną ).

Gdy constkwalifikuje funkcję składową, kwalifikacja odwołuje się do niejawnego thisargumentu. Innymi słowy, funkcja ta nie będzie mogła zmienić stanu obiektu, na którym jest wywoływana (obiekt wskazywany przez niejawny thiswskaźnik) - z wyjątkiem mutableobiektów, ale to już inna historia.

Aby powiedzieć to za pomocą kodu:

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;
};
Andy Prowl
źródło
11
Helluva, odpowiedz! Dziękuję Ci!
SexyBeast,
1
A więc w drugim przypadku, jeśli mam constprzedmiot objklasy Xi wołam bar()like obj.bar(obj), co ma się stać i dlaczego? Nie powinno obj._x = 42zawieść, skoro objjest zadeklarowane constw dzwoniącym?
SexyBeast
1
A co z przypadkiem, w którym sprawisz, że ostatnia funkcja paska ( void bar(X const& obj) {...}) będzie wyglądać tak? void bar(const X& obj) {...}, czy przeniesienie constsłowa kluczowego do tej lokalizacji coś zmienia? Jeśli tak, czy możesz dodać również ten przykład?
Gabriel Staples
1
@GabrielStaples Są takie same; constodnosi się do tego, co jest po jego lewej stronie lub do tego, co jest po jego prawej stronie, w przypadku gdy nie ma nic po lewej stronie. W twoim przypadku zobaczysz, że obie wersje constsą stosowane do X.
Andreas Flöjt
69

Metody klasy C ++ mają niejawny thisparametr, który występuje przed wszystkimi jawnymi. Czyli funkcja zadeklarowana w klasie takiej jak ta:

class C {
  void f(int x);

Możesz sobie wyobrazić, że naprawdę wygląda tak:

  void f(C* this, int x);

Teraz, jeśli zadeklarujesz to w ten sposób:

  void f(int x) const;

To tak, jakbyś napisał to:

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

Oznacza to, constże zakończenie powoduje, że thisparametr jest stały, co oznacza, że ​​można wywołać metodę na obiektach const typu klasy i że metoda nie może modyfikować obiektu, na którym została wywołana (przynajmniej nie za pośrednictwem normalnych kanałów).

John Zwinck
źródło
2
Idealnie poprawne, ale nie odpowiada na pytanie, które tak naprawdę nie odnosi się do metody klasowej, ale raczej do funkcji zaprzyjaźnionej.
mah
5
Tak, zdecydowałem się zignorować tę friendczęść, ponieważ uważam, że jest ona właściwie nieistotna dla prawdziwego pytania PO (lub tego, jakie prawdziwe pytanie stanie się, gdy wszystkie problemy wyjdą na jaw). Niech tak będzie.
John Zwinck,
Myślę, że powiedzenie „można wywołać metodę na obiektach stałych typu klasy” jest nieco mylące, ponieważ można wywołać metodę const na obiektach stałych lub obiektach innych niż const, podczas gdy funkcje inne niż const mogą być wywoływane tylko przez obiekty inne niż const. w przeciwnym razie jest to moja ulubiona odpowiedź
csguy
8
Circle copy(Circle&) const;

constsama tworzy funkcję . Może to być używane tylko dla funkcji składowych klasy / struktury.

Utworzenie funkcji członkowskiej constoznacza to

  • nie może wywoływać funkcji składowych innych niż const
  • nie może zmienić żadnych zmiennych składowych.
  • może być wywołane przez constobiekt ( constobiekty mogą wywoływać tylko constfunkcje). Obiekty niebędące stałymi mogą również wywołać constfunkcję.
  • To musi być funkcją składową klasy „ Kręgu ”.

Teraz rozważ następny:

Circle copy(const Circle &);

podczas gdy ten oznacza, że ​​przekazanego parametru nie można zmienić w funkcji. Może to być funkcja składowa klasy, ale nie musi.

UWAGA: Możliwe jest przeciążenie funkcji w taki sposób, aby mieć constwersję i nie stałą tej samej funkcji.

Waqar
źródło
7

WYJAŚNIJMY WSZYSTKIE NIEPRAWIDŁOWOŚCI ZWIĄZANE const


constpochodzi z ciągłego znaczenia, że ​​coś nie jest zmienne, ale czytelne.

  1. jeśli zakwalifikujemy naszą zmienną constsłowem kluczowym, nie będziemy mogli tego później zmienić.
    np. zmienna const musi zostać zainicjowana, gdy jest deklarowana.
    constint var =25;
    var =50; // gives error

  2. jeśli zakwalifikujemy naszą zmienną wskaźnika za pomocą after, nie możemy zmienić samego wskaźnika, ale zawartość wskaźnika jest zmienna . np. // aleconst *

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

    *ptr=5445; //allowed

  3. jeśli zakwalifikować naszą zmienną wskaźnika z przed potem można zmienić wskaźnik sobie, lecz zawartość wskaźnika jest nie zmienna . np. // aleconst *

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

    *ptr=5445; // gives error

  4. wskaźnik i zawartość są stałe,
    np
    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 &);
    tutaj const Circle oznacza, że ​​wartość Circle jest czytelna tylko, jeśli spróbujemy zmienić wartość funkcji Circle wewnątrz funkcji, to daje to błąd.
  2. friend Circle copy(Circle&) const;
    Ten typ funkcji nie jest przeznaczony dla zmiennej niebędącej składową. Jest on używany dla klasy lub struktury. Tutaj cała funkcja jest kwalifikowana słowem kluczowym const, co oznacza, że ​​nie możemy zmienić zmiennej składowej obiektu . na przykład
    class A{ public :
              int  var;
              void fun1()
                    { var = 50; // allowed
                    } 
              void fun2()const
                       { var=50; //not allowed
                       }
           }; 
Ramesh Choudhary
źródło
4

Jeden odnosi się do parametru, a drugi do funkcji.

Circle copy(const Circle &);

Oznacza to, że przekazanego parametru nie można zmienić w funkcji

Circle copy(Circle&) const;

constFunkcja kwalifikowana jest używany do funkcji składowych i oznacza, że nie można zmienić członków danych z samego obiektu. Podany przez Ciebie przykład był bezsensowny.

Czytaj od prawej do lewej

Jeśli przepiszemy pierwszą funkcję jako Circle copy(Circle const&);, co oznacza to samo, stanie się jasne, że czytanie od prawej do lewej staje się przydatne. copyto funkcja, która pobiera constodwołanie do Circleobiektu i zwraca Circleobiekt przez odwołanie.

Alex Chamberlain
źródło
0

friend Circle copy(const Circle &);// odnosi się do stałego parametru funkcji. cant 'zmień wartość przechowywaną przez parametr.

Musisz usunąć znajomego z twojego przykładowego Circle copy (Circle &) const; // nie można zmienić tej wartości poniter nazwanej jako stała funkcja składowa

shivakumar
źródło
-1
friend Circle copy(const Circle &);

Wartość parametru nie zostanie zmieniona podczas wywołań funkcji.

friend Circle copy(const Circle &)const ; 

Funkcja jest akcesorem, który nie zmienia żadnej wartości elementów członkowskich klasy. Ogólnie rzecz biorąc, istnieją typy funkcji: akcesory i mutatory. Accessor: sprawdza, ale nie zmienia stanu swojego obiektu.

Sam
źródło