Class declaration
Классы — это определяемые пользователем типы, определяемые спецификатором класса, который появляется в decl-specifier-seq синтаксиса объявления .
Содержание
СинтаксисСпецификатор класса имеет следующий синтаксис:
1) Определение именованного класса
2) Определение безымянного класса
Предварительное объявлениеОбъявление следующего вида
Объявляет тип класса, который будет определён позже в этой области видимости. До появления определения это имя класса имеет неполный тип . Это позволяет классам ссылаться друг на друга: class Vector; // предварительное объявление class Matrix { // ... friend Vector operator*(const Matrix&, const Vector&); }; class Vector { // ... friend Vector operator*(const Matrix&, const Vector&); }; и если конкретный исходный файл использует только указатели и ссылки на класс, это позволяет уменьшить #include зависимости: // В MyStruct.h #include <iosfwd> // содержит предварительное объявление std::ostream struct MyStruct { int value; friend std::ostream& operator<<(std::ostream& os, const S& s); // определение предоставлено в файле MyStruct.cpp, который использует #include <ostream> }; Если прямая декларация появляется в локальной области видимости, она скрывает ранее объявленный класс, переменную, функцию и все другие объявления с тем же именем, которые могут присутствовать во внешних областях видимости: struct s { int a; }; struct s; // ничего не делает (s уже определена в этой области видимости) void g() { struct s; // предварительное объявление новой локальной структуры "s" // это скрывает глобальную структуру s до конца этого блока s* p; // указатель на локальную структуру s struct s { char* p; }; // определение локальной структуры s } Обратите внимание, что новое имя класса также может быть введено с помощью elaborated type specifier (уточняющего спецификатора типа), который появляется как часть другого объявления, но только если name lookup (поиск имени) не может найти ранее объявленный класс с таким же именем. class U; namespace ns { class Y f(class T p); // объявляет функцию ns::f и объявляет ns::T и ns::Y class U f(); // U ссылается на ::U // можно использовать указатели и ссылки на T и Y Y* p; T* q; } Спецификация членовСпецификация членов, или тело определения класса, представляет собой заключенную в фигурные скобки последовательность любого количества следующих элементов:
1)
Объявления членов вида
Это объявление может объявлять статические и нестатические данные-члены и функции-члены , typedef-члены , перечисления-члены и вложенные классы . Также может быть friend-объявлением . class S { int d1; // non-static data member int a[10] = {1, 2}; // non-static data member with initializer (C++11) static const int d2 = 1; // static data member with initializer virtual void f1(int) = 0; // pure virtual member function std::string d3, *d4, f2(int); // two data members and a member function enum { NORTH, SOUTH, EAST, WEST }; struct NestedS { std::string s; } d5, *d6; typedef NestedS value_type, *pointer_type; };
2)
Определения функций, которые одновременно объявляют и определяют
функции-члены
или
дружественные функции
. Точка с запятой после определения функции-члена является необязательной. Все функции, определённые внутри тела класса, автоматически являются
встраиваемыми
, если они не привязаны к
именованному модулю
(начиная с C++20)
.
class M { std::size_t C; std::vector<int> data; public: M(std::size_t R, std::size_t C) : C(C), data(R*C) {} // constructor definition int operator()(std::size_t r, std::size_t c) const // member function definition { return data[r * C + c]; } int& operator()(std::size_t r, std::size_t c) // another member function definition { return data[r * C + c]; } };
3)
Спецификаторы доступа
public:
,
protected:
, и
private:
class S { public: S(); // public constructor S(const S&); // public copy constructor virtual ~S(); // public virtual destructor private: int* ptr; // private data member };
4)
Объявления using
:
class Base { protected: int d; }; class Derived : public Base { public: using Base::d; // делаем защищенный член d из Base открытым членом Derived using Base::Base; // наследуем все конструкторы базовых классов (C++11) };
5)
static_assert
объявления:
template<typename T> struct Foo { static_assert(std::is_floating_point<T>::value, "Foo<T>: T must be floating point"); };
6)
объявления шаблонов-членов
:
struct S { template<typename T> void f(T&& n); template<class CharT> struct NestedS { std::basic_string<CharT> s; }; };
Локальные классыОбъявление класса может находиться внутри тела функции, в этом случае оно определяет локальный класс . Имя такого класса существует только в пределах области видимости функции и недоступно извне.
Запустить этот код
#include <algorithm> #include <iostream> #include <vector> int main() { std::vector<int> v{1, 2, 3}; struct Local { bool operator()(int n, int m) { return n > m; } }; std::sort(v.begin(), v.end(), Local()); // since C++11 for (int n : v) std::cout << n << ' '; std::cout << '\n'; } Вывод: 3 2 1 Ключевые словаОтчеты о дефектахСледующие отчеты об изменениях в поведении, являющиеся дефектными, были применены ретроактивно к ранее опубликованным стандартам C++.
Смотрите также
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||