Який сенс const
у таких деклараціях? const
Мене бентежить.
class foobar
{
public:
operator int () const;
const char* foo() const;
};
Який сенс const
у таких деклараціях? const
Мене бентежить.
class foobar
{
public:
operator int () const;
const char* foo() const;
};
Відповіді:
Коли ви додасте const
ключове слово до методу, this
вказівник по суті стане вказівником на const
об’єкт, і тому ви не можете змінити будь-які дані учасника. (Якщо ви не користуєтеся mutable
, докладніше про це пізніше).
const
Ключове слово є частиною функцій підпису , яка означає , що ви можете реалізувати два подібних методів, один з яких викликається , коли об'єкт const
, і той , який не є.
#include <iostream>
class MyClass
{
private:
int counter;
public:
void Foo()
{
std::cout << "Foo" << std::endl;
}
void Foo() const
{
std::cout << "Foo const" << std::endl;
}
};
int main()
{
MyClass cc;
const MyClass& ccc = cc;
cc.Foo();
ccc.Foo();
}
Це виведе
Foo
Foo const
У методі non-const ви можете змінити елементи екземпляра, чого ви не можете зробити у const
версії. Якщо ви зміните декларацію методу у наведеному вище прикладі на код нижче, ви отримаєте деякі помилки.
void Foo()
{
counter++; //this works
std::cout << "Foo" << std::endl;
}
void Foo() const
{
counter++; //this will not compile
std::cout << "Foo const" << std::endl;
}
Це не зовсім вірно, тому що ви можете позначити члена як, mutable
і const
метод може потім змінити його. В основному використовується для внутрішніх лічильників та інших матеріалів. Рішення для цього буде наведеним нижче кодом.
#include <iostream>
class MyClass
{
private:
mutable int counter;
public:
MyClass() : counter(0) {}
void Foo()
{
counter++;
std::cout << "Foo" << std::endl;
}
void Foo() const
{
counter++; // This works because counter is `mutable`
std::cout << "Foo const" << std::endl;
}
int GetInvocations() const
{
return counter;
}
};
int main(void)
{
MyClass cc;
const MyClass& ccc = cc;
cc.Foo();
ccc.Foo();
std::cout << "Foo has been invoked " << ccc.GetInvocations() << " times" << std::endl;
}
які б вивели
Foo
Foo const
Foo has been invoked 2 times
Конст означає, що метод обіцяє не змінювати членів класу. Ви зможете виконати такі позначені члени об'єкта, навіть якщо сам об'єкт був позначений const
:
const foobar fb;
fb.foo();
було б законним.
Подивіться, скільки і для чого використовується “const” в C ++? для отримання додаткової інформації.
В const
означає класифікатор , що методи можуть бути викликані на будь-яке значення foobar
. Різниця виникає, коли ви розглядаєте виклик методу non-const об'єкту const. Подумайте, чи був у вашого foobar
типу таке додаткове декларація методу:
class foobar {
...
const char* bar();
}
Метод bar()
не const і до нього можна отримати лише значення, які не мають const.
void func1(const foobar& fb1, foobar& fb2) {
const char* v1 = fb1.bar(); // won't compile
const char* v2 = fb2.bar(); // works
}
Однак ідея const
полягає в тому, щоб позначити методи, які не змінять внутрішній стан класу. Це потужна концепція, але насправді не підлягає застосуванню в C ++. Це більше обіцянка, ніж гарантія. І той, який часто ламається і легко ламається.
foobar& fbNonConst = const_cast<foobar&>(fb1);
const
Хоч ідея хоч - позначити методи, які не змінять внутрішній стан класу". Це справді те, що я шукав.
const
?
Ці const означають, що компілятор помилиться, якщо метод 'with const' змінює внутрішні дані.
class A
{
public:
A():member_()
{
}
int hashGetter() const
{
state_ = 1;
return member_;
}
int goodGetter() const
{
return member_;
}
int getter() const
{
//member_ = 2; // error
return member_;
}
int badGetter()
{
return member_;
}
private:
mutable int state_;
int member_;
};
Тест
int main()
{
const A a1;
a1.badGetter(); // doesn't work
a1.goodGetter(); // works
a1.hashGetter(); // works
A a2;
a2.badGetter(); // works
a2.goodGetter(); // works
a2.hashGetter(); // works
}
Прочитайте це для отримання додаткової інформації
const
функції учасників, яке не згадує змінні , в кращому випадку є неповним.
Відповідь Блера знаходиться на позначці.
Однак зауважте, що є mutable
учасник класу даних, який може бути доданий. Будь-який член, зазначений таким чином, може бути модифікований const
методом без порушення const
договору.
Ви можете скористатися цим (наприклад), якщо ви хочете, щоб об'єкт запам'ятав, скільки разів викликається певний метод, при цьому це не впливає на "логічну" стійкість цього методу.
Значення функції члена-учасника в загальному знанні C ++: Основне проміжне програмування дає чітке пояснення:
Тип цього вказівника у функції non-const класу X є X * const. Тобто це постійний вказівник на неконстантний X (див. Const Pointers and Pointers to Const [7, 21]). Оскільки об'єкт, на який це посилається, не є const, він може бути модифікований. Тип цього у функції const члена класу X є const X * const. Тобто, це постійний вказівник на постійну X. Оскільки об'єкт, на який це посилається, є const, його неможливо змінити. Це різниця між функціями const і non-const.
Отже, у вашому коді:
class foobar
{
public:
operator int () const;
const char* foo() const;
};
Ви можете подумати так:
class foobar
{
public:
operator int (const foobar * const this) const;
const char* foo(const foobar * const this) const;
};
this
не є const
. Причина, по якій його неможливо змінити, полягає в тому, що це перше значення.
коли ви використовуєте const
в підписі методу (як ваш сказав const char* foo() const;
:), ви повідомляєте компілятору, на який вказувала пам'ять, this
не можна змінити цим методом (що foo
тут).
Я хотів би додати наступний пункт.
Ви також можете зробити це const &
іconst &&
Тому,
struct s{
void val1() const {
// *this is const here. Hence this function cannot modify any member of *this
}
void val2() const & {
// *this is const& here
}
void val3() const && {
// The object calling this function should be const rvalue only.
}
void val4() && {
// The object calling this function should be rvalue reference only.
}
};
int main(){
s a;
a.val1(); //okay
a.val2(); //okay
// a.val3() not okay, a is not rvalue will be okay if called like
std::move(a).val3(); // okay, move makes it a rvalue
}
Сміливо вдосконалюйте відповідь. Я не експерт
*this
завжди є значенням, навіть якщо функція члена відповідає кваліфікації rvalue і називається на rvalue. Приклад .
СопзЬ ключове слово , яке використовується з функцією декларація уточнюється , що вона є функцією члена Const , і він буде не в змозі змінити елементи даних об'єкта.
https://isocpp.org/wiki/faq/const-correctness#const-member-fns
Що таке "
const
функція члена"?Функція члена, яка інспектує (а не мутує) його об'єкт.
Функція-
const
член вказуєтьсяconst
суфіксом відразу після списку параметрів функції-члена. Функції членів ізconst
суфіксом називаються "функціями членів const" або "inspectors". Функції учасників безconst
суфікса називаються " функції, які не входять у склад", або "мутатори".class Fred { public: void inspect() const; // This member promises NOT to change *this void mutate(); // This member function might change *this }; void userCode(Fred& changeable, const Fred& unchangeable) { changeable.inspect(); // Okay: doesn't change a changeable object changeable.mutate(); // Okay: changes a changeable object unchangeable.inspect(); // Okay: doesn't change an unchangeable object unchangeable.mutate(); // ERROR: attempt to change unchangeable object }
Спроба викликати
unchangeable.mutate()
помилку, виявлена під час компіляції. Немає місця для виконання або штрафу за швидкістьconst
, і вам не потрібно писати тестові випадки, щоб перевірити це під час виконання.Функція трейлінгу
const
наinspect()
члені повинна використовуватися для того, щоб метод не змінив абстрактний стан (видимий для клієнта) об'єкта . Це трохи відрізняється від того, що сказати, що метод не змінить "необроблені біти" структури об'єкта. Компіляторам C ++ заборонено приймати "побітову" інтерпретацію, якщо вони не зможуть вирішити проблему зшивання, яку зазвичай неможливо вирішити (тобто може існувати псевдонім non-const, який міг би змінити стан об'єкта). Ще одне (важливе) розуміння цієї проблематики: вказівка на об'єкт з покажчиком на const не гарантує, що об'єкт не зміниться; він просто обіцяє, що об'єкт не зміниться через цей покажчик .