Чтение онлайн

на главную - закладки

Жанры

C++. Сборник рецептов

Когсуэлл Джефф

Шрифт:
Решение

Объявите переменную-член с ключевым словом

static
, затем инициализируйте ее в отдельном исходном файле (но не в заголовочном файле, где она объявлена), как показано в примере 8.5.

Пример 8.5. Использование статических переменных-членов

// Static.h

class OneStatic {

public:

 int getCount {return count;}

 OneStatic;

protected:

 static int count;

};

// Static.cpp

#include "Static.h"

int OneStatic::count = 0;

OneStatic::OneStatic {

 count++;

}

// StaticMain.cpp

#include <iostream>

#include "static.h"

using namespace std;

int main {

 OneStatic a;

 OneStatic b;

 OneStatic c;

 cout << a.getCount << endl;

 cout << b.getCount << endl;

 cout << c.getCount << endl;

}

Обсуждение

static
это способ C++ разрешить создание только одной копии чего-либо. Если переменную-член объявить как
static
, то будет создана только одна такая переменная вне зависимости от количества созданных объектов этого класса. Аналогично, если объявить как
static
переменную функции, она будет создана только один раз и будет хранить свое значение от одного вызова функции к другому. Однако в случае с переменными-членами, чтобы убедиться, что переменная создана правильно, требуется проделать несколько больше работы. Именно по этой причине в примере 8.5 показано три файла.

Во-первых, при объявлении переменной требуется использовать ключевое слово

static
. Это достаточно просто: добавьте это ключевое слово в заголовок класса, находящийся в заголовочном файле Static.h.

protected:

static int count;

После этого требуется определить эту переменную в исходном файле. При этом для нее будет выделена память. Это делается с помощью указания полного имени переменной и присвоения ей значения, как здесь.

int OneStatic::count = 0;

В примере 8.5 я поместил это определение в файл Static.cpp. Именно так вы и должны делать — не помещайте определение в заголовочный файл. Если это сделать, память будет выделена в каждом файле реализации, включающем этот заголовочный файл, и либо возникнут ошибки компиляции, либо, что хуже, в памяти появятся несколько экземпляров этой переменной. Это не то, что требуется при использовании переменной-члена

static
.

В главном файле StaticMain.cpp вы можете видеть то, что происходит. Создается несколько экземпляров

класса
OneStatic
, и каждый раз конструктор по умолчанию
OneStatic
инкрементирует статическую переменную. В результате вывод
main
из StaticMain.cpp имеет вид:

3

3

3

Каждый вызов

getCount
возвращает одно и то же целое значение, даже несмотря на то, что он делается для различных экземпляров класса.

8.6. Определение типа объекта во время выполнения

Проблема

Во время выполнения требуется динамически узнавать тип определенного класса.

Решение

Для запроса, на объект какого типа указывает адрес объекта, используйте идентификацию типов во время выполнения (обычно называемую просто RTTI — runtime type identification). Пример 8.6 показывает, как это делается.

Пример 8.6. Использование идентификации типов во время выполнения

#include <iostream>

#include <typeinfo>

using namespace std;

class Base {};

class Derived : public Base {};

int main {

 Base b, bb;

 Derived d;

 // Используем typeid для проверки равенства типов

 if (typeid(b) == typeid(d)) { // No

cout << "b и d имеют один и тот же тип.\n";

 }

 if (typeid(b) == typeid(bb)) { // Yes

cout << "b и bb имеют один и тот же тип.\n";

 }

 it (typeid(a) == typeid(Derived)) { // Yes

cout << "d имеет тип Derived.\n";

 }

}

Обсуждение

Пример 8.6 показывает, как использовать оператор

typeid
для определения и сравнения типов объектов,
typeid
принимает выражение или тип и возвращает ссылку на объект типа
type_info
или его подкласс (что зависит от реализации). Возвращенное значение можно использовать для проверки на равенство или получить строковое представление имени типа. Например, сравнить типы двух объектов можно так.

if (typeid(b) == typeid(d)) {

Это выражение возвращает истину, если возвращаемые объекты

type_info
равны. Это работает благодаря тому, что
typeid
возвращает ссылку на статический объект, так что при его вызове для двух объектов одного и того же типа будут получены две ссылки на один и тот же объект и сравнение вернет истину.

typeid
также можно использовать непосредственно с типом, как здесь.

if (typeid(d) == typeid(Derived)) {

Поделиться:
Популярные книги

Наследник чародея. Школяр. Книга первая

Рюмин Сергей
1. Наследник чародея
Фантастика:
городское фэнтези
5.00
рейтинг книги
Наследник чародея. Школяр. Книга первая

Проданная невеста

Wolf Lita
Любовные романы:
любовно-фантастические романы
5.80
рейтинг книги
Проданная невеста

Гардемарин Ее Величества. Инкарнация

Уленгов Юрий
1. Гардемарин ее величества
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Гардемарин Ее Величества. Инкарнация

Черт из табакерки

Донцова Дарья
1. Виола Тараканова. В мире преступных страстей
Детективы:
иронические детективы
8.37
рейтинг книги
Черт из табакерки

Новый Рал 9

Северный Лис
9. Рал!
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Новый Рал 9

Росток

Ланцов Михаил Алексеевич
2. Хозяин дубравы
Фантастика:
попаданцы
альтернативная история
фэнтези
7.00
рейтинг книги
Росток

Пять попыток вспомнить правду

Муратова Ульяна
2. Проклятые луной
Фантастика:
фэнтези
эпическая фантастика
5.00
рейтинг книги
Пять попыток вспомнить правду

Александр Агренев. Трилогия

Кулаков Алексей Иванович
Александр Агренев
Фантастика:
альтернативная история
9.17
рейтинг книги
Александр Агренев. Трилогия

Наследник с Меткой Охотника

Тарс Элиан
1. Десять Принцев Российской Империи
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Наследник с Меткой Охотника

Хозяйка старой пасеки

Шнейдер Наталья
Фантастика:
попаданцы
фэнтези
7.50
рейтинг книги
Хозяйка старой пасеки

Выйду замуж за спасателя

Рам Янка
1. Спасатели
Любовные романы:
современные любовные романы
7.00
рейтинг книги
Выйду замуж за спасателя

Искатель 2

Шиленко Сергей
2. Валинор
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Искатель 2

Мастер Разума III

Кронос Александр
3. Мастер Разума
Фантастика:
героическая фантастика
попаданцы
аниме
5.25
рейтинг книги
Мастер Разума III

Родословная. Том 2

Ткачев Андрей Юрьевич
2. Линия крови
Фантастика:
городское фэнтези
аниме
фэнтези
5.00
рейтинг книги
Родословная. Том 2