C++
const słowo kluczowe
Szukaj…
Składnia
- const Typ myVariable = initial; // Deklaruje zmienną const; nie może zostać zmieniony
- const Type & myReference = myVariable; // Deklaruje odniesienie do zmiennej const
- const Typ * myPointer = & myVariable; // Deklaruje wskaźnik do stałej. Wskaźnik może się zmienić, ale nie można zmienić podstawowego elementu danych za pomocą wskaźnika
- Wpisz * const myPointer = & myVariable; // Deklaruje stały wskaźnik. Nie można ponownie przypisać wskaźnika, aby wskazywał na coś innego, ale element danych będący podstawą może zostać zmieniony
- const Typ * const myPointer = & myVariable; // Deklaruje stałą wskaźnik do stałej.
Uwagi
Zmiennej oznaczonej jako const
nie można zmienić 1 . Próba wywołania na nim jakichkolwiek operacji non-const spowoduje błąd kompilatora.
1: Cóż, można to zmienić za pomocą const_cast
, ale prawie nigdy nie powinieneś tego używać
Stałe zmienne lokalne
Deklaracja i wykorzystanie.
// a is const int, so it can't be changed
const int a = 15;
a = 12; // Error: can't assign new value to const variable
a += 1; // Error: can't assign new value to const variable
Wiązanie referencji i wskaźników
int &b = a; // Error: can't bind non-const reference to const variable
const int &c = a; // OK; c is a const reference
int *d = &a; // Error: can't bind pointer-to-non-const to const variable
const int *e = &a // OK; e is a pointer-to-const
int f = 0;
e = &f; // OK; e is a non-const pointer-to-const,
// which means that it can be rebound to new int* or const int*
*e = 1 // Error: e is a pointer-to-const which means that
// the value it points to can't be changed through dereferencing e
int *g = &f;
*g = 1; // OK; this value still can be changed through dereferencing
// a pointer-not-to-const
Stałe wskaźniki
int a = 0, b = 2;
const int* pA = &a; // pointer-to-const. `a` can't be changed through this
int* const pB = &a; // const pointer. `a` can be changed, but this pointer can't.
const int* const pC = &a; // const pointer-to-const.
//Error: Cannot assign to a const reference
*pA = b;
pA = &b;
*pB = b;
//Error: Cannot assign to const pointer
pB = &b;
//Error: Cannot assign to a const reference
*pC = b;
//Error: Cannot assign to const pointer
pC = &b;
Funkcje składowe stałej
Funkcje składowe klasy można zadeklarować jako const
, co informuje kompilator i przyszłych czytelników, że ta funkcja nie zmodyfikuje obiektu:
class MyClass
{
private:
int myInt_;
public:
int myInt() const { return myInt_; }
void setMyInt(int myInt) { myInt_ = myInt; }
};
W funkcji const
this
wskaźnik jest faktycznie const MyClass *
zamiast MyClass *
. Oznacza to, że nie można zmieniać żadnych zmiennych składowych w ramach funkcji; kompilator wyśle ostrzeżenie. Tak więc setMyInt
nie mógł zostać zadeklarowany jako const
.
Prawie zawsze powinieneś oznaczać funkcje const
jako const
jeśli to możliwe. Tylko const
funkcje const
mogą być wywoływane na const MyClass
.
metod static
nie można zadeklarować jako const
. Jest tak, ponieważ metoda statyczna należy do klasy i nie jest wywoływana na obiekcie; dlatego nigdy nie może modyfikować wewnętrznych zmiennych obiektu. Dlatego deklarowanie metod static
jako const
byłoby zbędne.
Unikanie powielania kodu w metodach const i non-const getter.
W metodach C ++, które różnią się tylko kwalifikatorem const
można przeciążać. Czasami mogą być potrzebne dwie wersje gettera, które zwracają odniesienie do jakiegoś członka.
Niech Foo
będzie klasą, która ma dwie metody, które wykonują identyczne operacje i zwraca odwołanie do obiektu typu Bar
:
class Foo
{
public:
Bar& GetBar(/* some arguments */)
{
/* some calculations */
return bar;
}
const Bar& GetBar(/* some arguments */) const
{
/* some calculations */
return bar;
}
// ...
};
Jedyna różnica między nimi polega na tym, że jedna metoda nie jest stała i zwraca odwołanie inne niż stałe (które można wykorzystać do modyfikacji obiektu), a druga to stała i zwraca stałe odniesienie.
Aby uniknąć powielania kodu, istnieje pokusa, aby wywołać jedną metodę z drugiej. Nie możemy jednak wywołać metody non-const z const. Ale możemy wywołać metodę const z metody non-const. Będzie to wymagać użycia „const_cast” do usunięcia kwalifikatora const.
Rozwiązaniem jest:
struct Foo
{
Bar& GetBar(/*arguments*/)
{
return const_cast<Bar&>(const_cast<const Foo*>(this)->GetBar(/*arguments*/));
}
const Bar& GetBar(/*arguments*/) const
{
/* some calculations */
return foo;
}
};
W powyższym kodzie wywołujemy GetBar
wersję GetBar
z non-const GetBar
, przesyłając to do typu const: const_cast<const Foo*>(this)
. Ponieważ wywołujemy metodę const z non-const, sam obiekt jest non-const, a odrzucanie const jest dozwolone.
Przeanalizuj następujący, bardziej kompletny przykład:
#include <iostream>
class Student
{
public:
char& GetScore(bool midterm)
{
return const_cast<char&>(const_cast<const Student*>(this)->GetScore(midterm));
}
const char& GetScore(bool midterm) const
{
if (midterm)
{
return midtermScore;
}
else
{
return finalScore;
}
}
private:
char midtermScore;
char finalScore;
};
int main()
{
// non-const object
Student a;
// We can assign to the reference. Non-const version of GetScore is called
a.GetScore(true) = 'B';
a.GetScore(false) = 'A';
// const object
const Student b(a);
// We still can call GetScore method of const object,
// because we have overloaded const version of GetScore
std::cout << b.GetScore(true) << b.GetScore(false) << '\n';
}