Помните, что совместное использование глобального контейнера, как в примере 8.4, не будет работать, если объекты класса MyClassсоздаются в нескольких потоках. В этом случае требуется сериализация доступа к общему объекту через мьютексы. Рецепты, относящиеся к этой и другим методикам многопоточности, приведены в главе 12.
Если требуется отслеживать все экземпляры класса, можно также использовать шаблон фабрики. В целом это будет означать, что для создания нового объекта клиентский код вместо вызова оператора new должен будет вызывать функцию. За подробностями о том, как это делается, обратитесь к рецепту 8.2.
Смотри также
Рецепт 8.2.
8.5. Гарантия единственности копии переменной-члена
Проблема
Имеется переменная-член, у которой должен быть только один экземпляр независимо от числа создаваемых экземпляров класса. Этот тип переменных-членов обычно называется статическими членами или переменными класса — в противоположность переменным экземпляра , свои копии которых создаются для каждого объекта класса.
Решение
Объявите переменную-член с ключевым словом 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
#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
#include
using namespace std;
class Base {};
class Derived : public Base {};
Читать дальше