классы С++
Класс в C++ — это определяемый пользователем тип или структура данных , объявленная с помощью любого из ключевых слов. class
, struct
или union
(первые два вместе называются классами, не связанными с объединением), которые имеют данные и функции (также называемые переменными-членами и функциями-членами ) в качестве своих членов, доступ к которым регулируется тремя спецификаторами доступа: Private , Protected или Public . По умолчанию доступ к членам класса C++, объявленного с помощью ключевого слова class
является частным . Закрытые члены недоступны за пределами класса; доступ к ним возможен только через функции-члены класса. Открытые члены образуют интерфейс класса и доступны вне класса.
Экземпляры типа данных класса известны как объекты и могут содержать переменные-члены, константы , функции-члены и перегруженные операторы , определенные программистом.
Различия между struct
и class
на С++
[ редактировать ] В C++ класс, определенный с помощью class
имеет частные Ключевое слово по умолчанию члены и базовые классы. Структура — это класс, определенный с помощью struct
ключевое слово. [1] Его члены и базовые классы являются общедоступными по умолчанию . На практике структуры обычно зарезервированы для данных без функций. При получении структуры из класса/структуры спецификатор доступа по умолчанию для базового класса/структуры является общедоступным. А при наследовании класса спецификатор доступа по умолчанию является закрытым.
Совокупные классы
[ редактировать ]Агрегатный класс — это класс без объявленных пользователем конструкторов, без частных или защищенных нестатических элементов данных, без базовых классов и без виртуальных функций. [2] Такой класс можно инициализировать с помощью списка предложений-инициализаторов, заключенных в фигурные скобки и разделенных запятыми. [3] Следующий код имеет одинаковую семантику как на C, так и на C++.
struct C {
int a;
double b;
};
struct D {
int a;
double b;
C c;
};
// initialize an object of type C with an initializer-list
C c = {1, 2.0};
// D has a sub-aggregate of type C. In such cases initializer-clauses can be nested
D d = {10, 20.0, {1, 2.0}};
POD-структуры
[ редактировать ]POD -структура (простая старая структура данных) — это агрегатный класс без объединения, который не имеет нестатических элементов данных типа, отличного от POD-структуры, не-POD-объединения (или массива таких типов) или ссылки, и имеет нет определяемого пользователем оператора присваивания и определяемого пользователем деструктора . [1] Можно сказать, что POD-структура является эквивалентом C++ структуры C. struct
. В большинстве случаев структура POD будет иметь ту же структуру памяти, что и соответствующая структура, объявленная в C. [4] По этой причине структуры POD иногда в просторечии называют «структурами C-стиля». [5]
Свойства, общие для структур в C и структур POD в C++.
[ редактировать ]- Члены данных выделяются так, чтобы более поздние члены имели более высокие адреса внутри объекта, за исключением случаев, когда они разделены спецификатором доступа. [6]
- Два типа POD-структур совместимы по макету, если они имеют одинаковое количество нестатических элементов данных, а соответствующие нестатические элементы данных (по порядку) имеют типы, совместимые по макету. [7]
- POD-структура может содержать безымянное дополнение . [8]
- Указатель на объект POD-структуры, соответствующим образом преобразованный с помощью reinterpret cast , указывает на его начальный член и наоборот, подразумевая, что в начале POD-структуры нет заполнения. [8]
- POD-структуру можно использовать с макросом offsetof . [9]
Декларация и использование
[ редактировать ]Классы C++ имеют своих членов. Эти члены включают переменные (включая другие структуры и классы), функции (конкретные идентификаторы или перегруженные операторы), известные как функции-члены, конструкторы и деструкторы. Члены объявлены общедоступными или частными с использованием public:
и private:
спецификаторы доступа соответственно. Любой член, встречающийся после спецификатора, будет иметь соответствующий доступ до тех пор, пока не встретится другой спецификатор. Существует также наследование между классами, которое может использовать protected:
спецификатор.
Глобальный и локальный класс
[ редактировать ]Класс, определенный вне всех функций, является глобальным классом, поскольку его объекты можно создавать из любого места программы. Если он определен в теле функции, то это локальный класс, поскольку объекты такого класса являются локальными по отношению к области действия функции.
Базовое объявление и переменные-члены
[ редактировать ]Классы без объединения объявляются с помощью class
или struct
ключевое слово . Декларации членов размещаются внутри настоящей декларации.
struct Person {
string name;
int age;
};
|
class Person {
public:
string name;
int age;
};
|
Приведенные выше определения функционально эквивалентны. Любой код будет определять объекты типа Person
как имеющий два элемента общедоступных данных, name
и age
. Точки с запятой после закрывающих скобок обязательны.
После одного из этих заявлений (но не обоих) Person
может использоваться следующим образом для создания вновь определенных переменных Person
тип данных:
#include <iostream>
#include <string>
struct Person {
std::string name;
int age;
};
int main() {
Person a;
Person b;
a.name = "Calvin";
b.name = "Hobbes";
a.age = 30;
b.age = 20;
std::cout << a.name << ": " << a.age << std::endl;
std::cout << b.name << ": " << b.age << std::endl;
}
Выполнение приведенного выше кода выведет
Calvin: 30 Hobbes: 20
Функции-члены
[ редактировать ]Важной особенностью класса C++ являются функции-члены . Каждый тип данных может иметь свои собственные встроенные функции (называемые функциями-членами), которые имеют доступ ко всем (открытым и частным) членам типа данных. В теле этих нестатических функций-членов ключевое слово this
может использоваться для ссылки на объект, для которого вызывается функция. Обычно это реализуется путем передачи адреса объекта в качестве неявного первого аргумента функции. [10] Возьмите вышеизложенное Person
введите в качестве примера еще раз:
#include <iostream>
class Person {
public:
void Print() const;
private:
std::string name_;
int age_=5; //C++ 11
};
void Person::Print() const {
std::cout << name_ << ':' << age_ << '\n';
// "name_" and "age_" are the member variables. The "this" keyword is an
// expression whose value is the address of the object for which the member
// was invoked. Its type is "const Person*", because the function is declared
// const.
}
В приведенном выше примере Print
Функция объявляется в теле класса и определяется путем указания имени класса, за которым следует ::
. Оба name_
и age_
являются частными (по умолчанию для класса) и Print
объявлен как общедоступный, что необходимо, если он будет использоваться вне класса.
С функцией-членом Print
печать можно упростить до:
a.Print();
b.Print();
где a
и b
выше называются отправителями, и каждый из них будет ссылаться на свои собственные переменные-члены, когда Print()
функция выполняется.
Обычной практикой является разделение объявления класса или структуры (называемого его интерфейсом) и определения (называемого его реализацией) на отдельные блоки. Интерфейс, необходимый пользователю, хранится в заголовке , а реализация хранится отдельно в исходной или скомпилированной форме.
Наследование
[ редактировать ]Расположение классов, не относящихся к POD, в памяти не определяется стандартом C++. Например, многие популярные компиляторы C++ реализуют одиночное наследование путем объединения полей родительского класса с полями дочернего класса, но стандарт этого не требует. Такой выбор макета делает обращение к производному классу через указатель на тип родительского класса тривиальной операцией.
Например, рассмотрим
struct P {
int x;
};
struct C : P {
int y;
};
Пример P
с P* p
указание на него может выглядеть в памяти так:
┏━━━━┓ ┃P::x┃ ┗━━━━┛ ↑ p
Пример C
с P* p
указание на это может выглядеть так:
┏━━━━┳━━━━┓ ┃P::x┃C::y┃ ┗━━━━┻━━━━┛ ↑ p
Следовательно, любой код, который манипулирует полями P
объект может манипулировать P
поля внутри C
объект без необходимости рассматривать что-либо об определении C
поля. В любом случае правильно написанная программа на C++ не должна делать никаких предположений о расположении наследуемых полей. Использование static_cast или Dynamic_cast операторов преобразования типов гарантирует правильное преобразование указателей из одного типа в другой.
Множественное наследование не так просто. Если класс D
наследует P
и C
, то поля обоих родительских классов должны храниться в некотором порядке, но (максимум) только один из родительских классов может располагаться в начале производного класса. Всякий раз, когда компилятору необходимо преобразовать указатель из D
введите либо P
или C
, компилятор обеспечит автоматическое преобразование адреса производного класса в адрес полей базового класса (обычно это простой расчет смещения).
Дополнительные сведения о множественном наследовании см. в разделе виртуальное наследование .
The final
Ключевое слово ограничивает способы класса создания подклассов . [11] Подклассам класса запрещено переопределять методы, помеченные как final
по родительскому классу. [12] [13] Заключительные классы не могут быть унаследованы. [13] Это позволяет провести девиртуализацию , отказаться от использования виртуальных таблиц для поиска методов, что позволяет встраивать вызовы методов в конечные классы. [14] [15]
final
не является зарезервированным словом в C++, а вместо этого определяется как контекстное ключевое слово , чтобы не конфликтовать с использованием идентификатора «final» в существующих базах кода. [16] [17]
Перегруженные операторы
[ редактировать ]В C++ такие операторы , как + - * /
, может быть перегружен в соответствии с потребностями программистов. Эти операторы называются перегружаемыми операторами .
По соглашению, перегруженные операторы должны вести себя почти так же, как и встроенные типы данных ( int
, float
и т. д.), но это не обязательно. Можно объявить структуру под названием Integer
в котором переменная действительно хранит целое число, но путем вызова Integer * Integer
вместо произведения целых чисел может быть возвращена сумма:
struct Integer {
Integer() = default;
Integer(int j) : i{j} {}
Integer operator*(const Integer& k) const {
return Integer(i + k.i);
}
int i = 0;
};
В приведенном выше коде использовался конструктор для «создания» возвращаемого значения. Для более наглядного представления (хотя это может снизить эффективность программы, если компилятор не сможет оптимизировать оператор до эквивалентного выше), приведенный выше код можно переписать так:
Integer operator*(const Integer& k) const {
Integer m;
m.i = i + k.i;
return m;
}
Программисты также могут поместить прототип оператора в struct
объявление и определите функцию оператора в глобальной области видимости:
struct Integer {
Integer() = default;
Integer(int j) : i{j} {}
Integer operator*(const Integer& k) const;
int i = 0;
};
Integer Integer::operator*(const Integer& k) const {
return Integer(i * k.i);
}
i
выше представляет собственную переменную-член отправителя, а k.i
представляет переменную-член из переменной аргумента k
.
The const
Ключевое слово появляется дважды в приведенном выше коде. Первое вхождение, аргумент const integer& k
, указывает на то, что переменная аргумента не будет изменена функцией. Второй случай в конце объявления обещает компилятору , что отправитель не будет изменен при запуске функции.
В const integer& k
, амперсанд (&) означает «передавать по ссылке». При вызове функции ей будет передана ссылка на переменную, а не значение переменной.
Обратите внимание, что арность , ассоциативность и приоритет операторов изменить нельзя.
Бинарные перегружаемые операторы
[ редактировать ]Бинарные операторы (операторы с двумя аргументами) перегружаются путем объявления функции с оператором-идентификатором (что-то), который вызывает один единственный аргумент. Переменная слева от оператора — это отправитель, а переменная справа — аргумент.
Integer i = 1;
/* we can initialize a structure variable this way as
if calling a constructor with only the first
argument specified. */
Integer j = 3;
/* variable names are independent of the names of the
member variables of the structure. */
Integer k = i * j;
std::cout << k.i << '\n';
Будет напечатано «3».
Ниже приведен список двоичных перегружаемых операторов:
Оператор | Общее использование |
---|---|
+ - * / % | Арифметический расчет |
^ & ! << >> | Побитовое вычисление |
< > == != <= >= | Логическое сравнение |
&& | Логическое соединение |
|| | Логическая дизъюнкция |
= <<= >>= | Сложное задание |
, | (без общего использования) |
Оператор '=' (присваивание) между двумя переменными одного и того же типа структуры по умолчанию перегружается для копирования всего содержимого переменных из одной в другую. При необходимости его можно перезаписать чем-нибудь другим.
Операторы должны перегружаться один за другим, другими словами, никакие перегрузки не связаны друг с другом. Например, <
не обязательно является противоположностью >
.
Унарные перегружаемые операторы
[ редактировать ]Хотя некоторые операторы, как указано выше, принимают два термина: отправителя слева и аргумента справа, некоторые операторы имеют только один аргумент — отправителя, и их называют «унарными». Примерами являются знак минус (когда слева от него ничего не ставится) и «логическое НЕ » ( восклицательный знак , !
).
Отправитель унарных операторов может находиться слева или справа от оператора. Ниже приведен список унарных перегружаемых операторов:
Оператор | Общее использование | Должность отправителя |
---|---|---|
+ - | Положительный/отрицательный знак | верно |
* & | Разыменование | верно |
! ~ | Логическое/побитовое НЕ | верно |
++ -- | Предварительное увеличение/уменьшение | верно |
++ -- | Пост-инкремент/декремент | левый |
Синтаксис перегрузки унарного оператора, где отправитель находится справа, следующий:
return_type operator@ ()
Когда отправитель находится слева, декларация выглядит следующим образом:
return_type operator@ (int)
@
выше означает перегрузку оператора. Заменять return_type
с типом данных возвращаемого значения ( int
, bool
, конструкции и т. д.)
The int
По сути, параметр означает не что иное, как соглашение, показывающее, что отправитель находится слева от оператора.
const
аргументы могут быть добавлены в конец объявления, если это применимо.
Перегрузка кронштейнов
[ редактировать ] этого раздела Фактическая точность оспаривается . ( январь 2009 г. ) |
Квадратная скобка []
и круглая скобка ()
может быть перегружен в классах C++. Квадратная скобка должна содержать ровно один аргумент, а круглая скобка может содержать любое определенное количество аргументов или не содержать аргументов.
Следующее объявление перегружает квадратную скобку.
return_type operator[] (argument)
Содержимое внутри скобок указано в argument
часть.
Круглый кронштейн перегружается аналогичным образом.
return_type operator() (arg1, arg2, ...)
Содержимое скобки в вызове оператора указывается во второй скобке.
Помимо указанных выше операторов, оператор стрелки ( ->
), звездчатая стрелка ( ->*
), new
ключевое слово и delete
Ключевое слово также может быть перегружено. Эти операторы, связанные с памятью или указателем, должны обрабатывать функции выделения памяти после перегрузки. Понравилось задание( =
) оператор, они также перегружаются по умолчанию, если не сделано никакого специального объявления.
Конструкторы
[ редактировать ] этого раздела Фактическая точность оспаривается . ( январь 2009 г. ) |
Иногда программисты могут захотеть, чтобы их переменные при объявлении принимали значение по умолчанию или определенное значение. Это можно сделать путем объявления конструкторов .
Person::Person(string name, int age) {
name_ = name;
age_ = age;
}
Переменные-члены можно инициализировать в списке инициализаторов с использованием двоеточия, как в примере ниже. Это отличается от описанного выше тем, что инициализируется (с использованием конструктора), а не с помощью оператора присваивания. Это более эффективно для типов классов, поскольку его нужно просто сконструировать напрямую; тогда как при присваивании их необходимо сначала инициализировать с помощью конструктора по умолчанию, а затем присвоить другое значение. Также некоторые типы (например, ссылки и константные типы) не могут быть назначены и поэтому должны быть инициализированы в списке инициализаторов.
Person(std::string name, int age) : name_(name), age_(age) {}
Обратите внимание, что фигурные скобки нельзя опускать, даже если они пусты.
Значения по умолчанию могут быть присвоены последним аргументам, чтобы облегчить инициализацию значений по умолчанию.
Person(std::string name = "", int age = 0) : name_(name), age_(age) {}
Если в приведенном выше примере конструктору не переданы аргументы, это эквивалентно вызову следующего конструктора без аргументов (конструктор по умолчанию):
Person() : name_(""), age_(0) {}
Объявление конструктора выглядит как функция с тем же именем, что и тип данных. Фактически вызов конструктора может принимать форму вызова функции. В этом случае инициализированный Person
Переменную типа можно рассматривать как возвращаемое значение:
int main() {
Person r = Person("Wales", 40);
r.Print();
}
Альтернативный синтаксис, который делает то же самое, что и приведенный выше пример:
int main() {
Person r("Wales", 40);
r.Print();
}
Конкретные действия программы, которые могут относиться или не относиться к переменной, могут быть добавлены как часть конструктора.
Person() {
std::cout << "Hello!" << std::endl;
}
С помощью приведенного выше конструктора команда "Hello!" будет напечатано, когда по умолчанию Person
вызывается конструктор.
Конструктор по умолчанию
[ редактировать ]Конструкторы по умолчанию вызываются, когда конструкторы не определены для классов.
struct A {
int b;
};
// Object created using parentheses.
A* a = new A(); // Calls default constructor, and b will be initialized with '0'.
// Object created using no parentheses.
A* a = new A; // Allocate memory, then call default constructor, and b will have value '0'.
// Object creation without new.
A a; // Reserve space for a on the stack, and b will have an unknown garbage value.
Однако если для класса был определен пользовательский конструктор , оба приведенных выше объявления вызовут этот пользовательский конструктор, чей определенный код будет выполнен, но переменной b не будут присвоены никакие значения по умолчанию.
эсминцы
[ редактировать ] этого раздела Фактическая точность оспаривается . ( январь 2009 г. ) |
Деструктор является обратным конструктору. Он вызывается, когда экземпляр класса уничтожается, например, когда объект класса, созданный в блоке (набор фигурных скобок «{}»), удаляется после закрывающей скобки, тогда деструктор вызывается автоматически. Он будет вызван при очистке области памяти, в которой хранятся переменные. Деструкторы можно использовать для освобождения ресурсов, таких как выделенная в куче память и открытые файлы, когда экземпляр этого класса уничтожается.
Синтаксис объявления деструктора аналогичен синтаксису конструктора. Возвращаемого значения нет, а имя функции совпадает с именем класса с тильдой (~) впереди.
~Person() {
std::cout << "I'm deleting " << name_ << " with age " << age_ << std::endl;
}
Сходства между конструкторами и деструкторами
[ редактировать ]- Оба имеют то же имя, что и класс, в котором они объявлены.
- Если они не объявлены пользователем, оба доступны в классе по умолчанию, но теперь они могут выделять и освобождать память у объектов класса только при объявлении или удалении объекта.
- Для производного класса: во время выполнения конструктора базового класса конструктор производного класса еще не вызывался; во время выполнения деструктора базового класса уже был вызван деструктор производного класса. В обоих случаях переменные-члены производного класса находятся в недопустимом состоянии.
Шаблоны классов
[ редактировать ]В C++ объявления классов могут создаваться на основе шаблонов классов. Такие шаблоны классов представляют собой семейство классов. Фактическое объявление класса получается путем создания экземпляра шаблона с одним или несколькими аргументами шаблона. Шаблон, созданный с определенным набором аргументов, называется специализацией шаблона.
Характеристики
[ редактировать ]Синтаксис C++ пытается сделать каждый аспект класса похожим на базовые типы данных . Таким образом, перегруженные операторы позволяют манипулировать классами точно так же, как целыми числами и числами с плавающей запятой, а массивы классов можно объявлять с помощью синтаксиса квадратных скобок ( some_structure variable_name[size]
), а указатели на классы можно разыменовывать так же, как указатели на встроенные типы данных.
Потребление памяти
[ редактировать ]Потребление памяти структурой представляет собой как минимум сумму размеров памяти составляющих переменных. Возьмите TwoNums
структуру ниже в качестве примера.
struct TwoNums {
int a;
int b;
};
Структура состоит из двух целых чисел. Во многих современных компиляторах C++ целые являются 32-битными числа по умолчанию , поэтому каждая переменная-член занимает четыре байта памяти. Таким образом, вся структура занимает не менее (или ровно) восемь байт памяти, как показано ниже.
+----+----+ | a | b | +----+----+
Однако компилятор может добавить заполнение между переменными или в конце структуры, чтобы обеспечить правильное выравнивание данных для данной компьютерной архитектуры, часто дополняя переменные для выравнивания по 32 битам. Например, структура
struct BytesAndSuch {
char c;
char C;
char D;
short int s;
int i;
double d;
};
может выглядеть как
+-+-+-+-+--+--+----+--------+ |c|C|D|X|s |XX| i | d | +-+-+-+-+--+--+----+--------+
в памяти, где X представляет дополненные байты на основе выравнивания по 4 байтам.
Поскольку структуры могут использовать указатели и массивы для объявления и инициализации своих переменных-членов, потребление памяти структурами не обязательно является постоянным . Другим примером непостоянного размера памяти являются шаблонные структуры.
Битовые поля
[ редактировать ]Битовые поля используются для определения членов класса, которые могут занимать меньше памяти, чем целочисленный тип. Это поле применимо только для целочисленных типов (int, char, short, long и т. д.) и типов перечислений (например, std::byte) и исключает float или double.
struct A {
unsigned a:2; // Possible values 0..3, occupies first 2 bits of int
unsigned b:3; // Possible values 0..7, occupies next 3 bits of int
unsigned :0; // Moves to end of next integral type
unsigned c:2;
unsigned :4; // Pads 4 bits in between c & d
unsigned d:1;
unsigned e:3;
};
- Структура памяти
4 byte int 4 byte int [1][2][3][4][5][6][7][8] [1] [2] [3] [4] [a][a][b][b][b][ ][ ][ ] [ ][ ][ ][ ][ ][ ][ ][ ] [ ][ ][ ][ ][ ][ ][ ][ ] [ ][ ][ ][ ][ ][ ][ ][ ] [5] [6] [7] [8] [c][c][ ][ ][ ][ ][d][e] [e][e][ ][ ][ ][ ][ ][ ] [ ][ ][ ][ ][ ][ ][ ][ ] [ ][ ][ ][ ][ ][ ][ ][ ]
Объединения также могут иметь элементы битового поля:
union A {
unsigned a:2;
unsigned b:3;
unsigned :0; // Does nothing
unsigned c:2;
unsigned :4; // Does nothing in this case; if the bit-field's width were large enough, it would change the union's size to fit
unsigned d:1;
unsigned e:3;
};
Перейти по ссылке
[ редактировать ]Многие программисты предпочитают использовать амперсанд (&) для объявления аргументов функции, включающей структуры. Это связано с тем, что при использовании амперсанда разыменования в функцию необходимо передать только одно слово (обычно 4 байта на 32-битной машине, 8 байтов на 64-битной машине), а именно место в памяти, где находится переменная. В противном случае, если используется передача по значению, аргумент необходимо копировать каждый раз при вызове функции, что является дорогостоящим для больших структур.
Поскольку передача по ссылке предоставляет исходную структуру, которая может быть изменена функцией, const
Ключевое слово следует использовать, чтобы гарантировать, что функция не изменит параметр (см. const-correctness ), когда это не предусмотрено.
Это слово ключевое
[ редактировать ]Чтобы облегчить классам возможность ссылаться на себя, в C++ реализован метод this
ключевое слово для всех функций-членов. this
Ключевое слово действует как указатель на текущий объект. [18] Его тип — указатель на текущий объект.
The this
Ключевое слово особенно важно для функций-членов, в которых в качестве возвращаемого значения используется сам класс:
Complex& operator+=(const Complex& c) {
real_part_ += c.real_part_;
imag_part_ += c.imag_part_;
return *this;
}
Как указано выше, this
является указателем, поэтому необходимо использовать звездочку ( *) для преобразования его в возвращаемую ссылку.
См. также
[ редактировать ]- Модификаторы доступа
- Виртуальное наследование
- Класс (компьютерное программирование)
- Программирование на основе классов
- Состав объекта
- Преобразование типов
- окончательный (С++)
Ссылки
[ редактировать ]- ^ Jump up to: а б ИСО / МЭК (2003). ISO/IEC 14882:2003(E): Языки программирования. C++ §9. Классы [класс], параграф. 4
- ^ ИСО / МЭК (2003). ISO/IEC 14882:2003(E): Языки программирования – C++ §8.5.1 Агрегаты [dcl.init.aggr] , параграф. 1
- ^ ИСО / МЭК (2003). ISO/IEC 14882:2003(E): Языки программирования – C++ §8.5.1 Агрегаты [dcl.init.aggr] , параграф. 2
- ^ «Что это за штука «POD» в C++, о которой я все время слышу?» . Комо Компьютеры. Архивировано из оригинала 19 января 2009 г. Проверено 20 января 2009 г.
- ^ Хенриксон, Матс; Найквист, Эрик (1997). Промышленная мощь C++ . Прентис Холл. ISBN 0-13-120965-5 .
- ^ ИСО / МЭК (2003). ISO/IEC 14882:2003(E): Языки программирования – C++ §9.2 Члены класса [class.mem] , параграф. 12
- ^ ИСО / МЭК (2003). ISO/IEC 14882:2003(E): Языки программирования – C++ §9.2 Члены класса [class.mem] , параграф. 14
- ^ Jump up to: а б ИСО / МЭК (2003). ISO/IEC 14882:2003(E): Языки программирования – C++ §9.2 Члены класса [class.mem] , параграф. 17
- ^ ИСО / МЭК (2003). ISO/IEC 14882:2003(E): Языки программирования – C++ §18.1 Типы [lib.support.types] , параграф. 5
- ^ «этот вызов (C++)» . Проверено 26 января 2009 г.
- ^ Международный стандарт ISO / IEC 14882: 2020 (E) - Язык программирования C ++.
- ^ Браунинг, Дж. Бертон; Сазерленд, Брюс (2020), Браунинг, Дж. Бертон; Сазерленд, Брюс (ред.), «Наследование» , Рецепты C++20: подход «проблема-решение» , Беркли, Калифорния: Apress, стр. 205–207, doi : 10.1007/978-1-4842-5713-5_6 , ISBN 978-1-4842-5713-5 , получено 24 апреля 2024 г.
- ^ Jump up to: а б Лакос, Джон; Ромео, Витторио; Хлебников, Ростислав; Мередит, Алисдер (16 декабря 2021 г.). Безопасное использование современного C++ . Аддисон-Уэсли Профессионал. ISBN 978-0-13-738051-0 .
- ^ «16BPP.net: Блог / Влияние «последнего» ключевого слова C++ на производительность» . 16bpp.net . Проверено 23 апреля 2024 г.
- ^ Брэнд, Сай (02 марта 2020 г.). «Преимущества производительности выпускных занятий» . Блог команды C++ . Проверено 23 апреля 2024 г.
- ^ ТайлерMSFT (3 августа 2021 г.). «конечный спецификатор» . Learn.microsoft.com . Проверено 23 апреля 2024 г.
- ^ Страуструп, Бьярне (10 июля 2013 г.). Язык программирования C++ . Аддисон-Уэсли. ISBN 978-0-13-352285-3 .
- ^ "этот" . Справочник по С++ .
Общие ссылки:
- Учебный урок Cplusplus.com 5.2. Архивировано 3 апреля 2009 г. на Wayback Machine , доступ осуществлен в январе 2006 г.
- Учебный урок Cplusplus.com 2.5. Архивировано 30 марта 2009 г. на Wayback Machine , доступ осуществлен в феврале 2006 г.