Страницы

Поиск по вопросам

четверг, 5 декабря 2019 г.

Определение и реализация

#cpp


У методов в классе есть приставки virtual и тп, а так же после метода const, override,
final, & и тп.

Как они классифицируются, называются (до и после)? Есть предположение что все что
после пишется в реализации, а не только в определении, метода, а до - нет, верно ли это?

На en.cppreference.com не нашел такого разделения, ткните пожалуйста.
    


Ответы

Ответ 1



Есть сигнатуры (типы) функций, и есть ключевые слова (спецификаторы), которые добавляются к объявлению функции-члена класса. Сигнатуры функций должны повторяться в объявлении функции, и в ее определении. Ключевые слова static, virtual, override, final, = 0 - используются только при объявлении функции, в теле класса. Это можно проиллюстрировать так: using F = void(); // сигнатура функции (в т.ч. члена класса) using M1 = void() const; // сигнатура, может быть только у членов класса using M2 = void() const &; F f; // объявление функции f с сигнатурой F void f() {} // определение функции f struct X { F f1; // объявление функции-члена класса f1 с сигнатурой F static F f2; // объявление статической функции-члена класса virtual F f3; // объявление виртуальной функции-члена класса virtual F f4 = 0; // объявление чисто-виртуальной функции-члена класса virtual M1 m1 = 0; virtual M2 m2 = 0; }; void X::f1() {} // Определения функций f1, f2, f3 void X::f2() {} void X::f3() {} struct Y : X { F f4 override; // переопределения виртуальных функций f4, m1, m2 virtual M1 m1; M2 m2 final; }; void Y::f4 {} // Определения функций f4, m1, m2 void Y::m1 const {} void Y::m2 const & {} То, с какой стороны находятся ключевые слова static, virtual, override, final, = 0 - определяется синтаксисом С++.

Ответ 2



Всё что входит в сигнатуру функции должно повторяться в ее объявлениях/определениях – (c) Abyx const SomeType method1(); SomeType method2() const; это разные методы (функции) с разными сигнатурами. Первая возвращает константный объект типа SomeType, вторая возвращает обычный (неконстантный) объект того же типа, но не имеет права модифицировать объект, от имени которого вызывается. Законченный пример кода: #include using namespace std; class A { public: A() : x(0) {} const int m1() { x = 1; return x; } // warning: type qualifiers ignored // on function return type int const m11() { x = 1; return x; } // absolutely same as m1 int m2() const { return x; } // but will not compile if you add x = 1; const A m3() { return A(); } A m4() const { return A(); } const A m5() { x = 1; return A(); } // ok A m6() const { x = 1; return A(); } // error private: int x; }; int main() { A a; cout << "Hello World!" << endl; cout << a.m3().m1() << endl; // error: passing const A as 'this' argument of // 'const A::m1()' discards qualifiers cout << a.m3().m2() << endl; // but this works cout << a.m4().m1() << endl; // and this works too return 0; } Вообще, спецификаторы virtual, override, final - относятся только непосредственно к самой функции, в отличие от квалификатора const, который может относится как к функции (если находится справа от имени функции-метода), так и к возвращаемому значению (слева от имени функции). Нужно помнить, что const всегда относится к тому, что непосредственно слева от него, за исключением случая, когда const - самое первое слова и тогда относится к тому, что непосредственно справа: int const * a // pointer to const int, same as const int * a int * const b // const pointer to int PS Объяснить, почему спецификатор virtual должен быть слева, а final - справа - я не могу. Для обычных функций (НЕ методов): int q() const { return 1; } // error: non-member function cannot have cv-qualifier int & f() { int *a = new int; *a = 0; return *a; } const int & g() { int *a = new int; *a = 0; return *a; } cout << f() << endl; // ok 0 cout << g() << endl; // ok 0 cout << ++f() << endl; // ok 1 cout << ++g() << endl; // error: increment of read only location g()

Комментариев нет:

Отправить комментарий