const метод: метод принимает первым аргументом неявно this, как константную ссылку. в таком методе нельзя менять значения полям, зато можно вызывать от константных объектов (если вызвать не const метод у const объекта, то CE) (const все ещё относится к сигнатуре, потому что const всё ещё относится к типу) когда метод константный и есть поля-ссылки, то const на них не влияет (навешивается справа, что не влияет)
static метод: не относятся ни к одному объекту, т.е. не имеет this первым аргументом неявно и не имеет доступа к полям. чтобы дать доступ к публичным полям, нужно явно по ссылке передать объект. нельзя сделать const. как обычная функция, но объявлена внутри неймспейса класса
static поля: не относятся ни к одному объекту конкретно, а относятся ко всему классу в целом. просто статическая переменная, которая объявлена в неймспейсе класса стандарт с++ запрещает внутриклассовую инициализацию неконстантных статических полей. чтобы не было переопределения статического поля, тк у них external linkage. статические константные переменные можно определять в классе, однако это будет считаться лишь объявлением можно определить статическое поле прям в классе, если написать inline (C++17)
mutable: ни при каких условиях переменная не будет константной можно сделать mutable поля и изменять их const методами применяется только к нестатическим полям
explicit: ключевое слово для объявления метода. Запрещает использовать для выполнения неявных преобразований советуется делать конструкторы от 1 аргумента и операторы конверсии explicit зачастую навешивают на конструкторы и операторы приведения типа
constexpr: вызов этого метода мы хотим считать constant expression (то, что может быть вычислено на этапе компиляции), никак не связано с const любую функцию, которую мы хотим вызвать в compile-time должна быть constexpr не обязательно вычисляется в compile-time, не обязывает вызывать только от constant expressions. означает лишь, что мы можем использовать вызов этой функции там, где ожидается constexpr
указатель на метод это не просто указатель на функцию он состоит из 2 частей: одна хранит адрес функции, а другая сдвиг - число, показывающая на сколько байт от начала объекта, чей это метод, сдвинуто начало объекта, от которого вызвались (в случае с наследованием: число, показывающее насколько нужная родительская часть сдвинута в наследнике) там неявно передаётся первым параметром указатель на объект (будущий this). Так вот, то самое смещение, которое хранится вторым - оно применяется именно к этому указателю, не на функцию, а на неявно переданный указатель объекта.
sizeof указателя на метод - 16
noexcept: гарантия, что функция не выкинет исключение. можно бросать исключения в функции, но обязаны поймать на этом же уровне. noexcept’ом помечаются функции, которые не могут пойти неудачно std::terminate если исключение из функции все же было выброшено
для шаблонных функций можно поставить noexcept в зависимости от каких либо условий
void f() noexcept(std::is_reference_v<T>) //compile-time проверяемое условие
^ cпецификатор noexcept
есть еще оператор noexcept - в compile-time проверяет, является ли выражение noexcept
std::cout << noexcept(g<T>()) // true/false
noexcept являются все операторы, кроме:
- new
- dynamic_cast
- typeid
- throw
void f() noexcept(noexcept(g<T>())) {}- функция noexcept <=> когда вызов g с параметром T был noexcept