|
Программирование >> Перегруженные имена функций и идентификаторы
static Fred* ans = new Fred(); return *ans; Поскольку локальные статические объекты создаются в момент, когда программа в процессе работы в первый раз проходит через точку их объявления, инструкция new Fred() в примере выше будет выполнена только один раз: во время первого вызова функции x(). Каждый последующий вызов возвратит тот же самый объект Fred (тот, на который указывает ans). И далее все случаи использования объекта x замените на вызовы функции x(): File Barney.cpp #include Barney.hpp Barney::Barney() ... x().goBowling(); ... Это и называется создание при первом использовании , глобальный объект Fred создается при первом обращении к нему. Отрицательным моментом этой техники является тот факт, что объект Fred нигде не уничтожается. Примечание: ошибки статической инициализации не распространяются на базовые/встроенные типы, такие как int или char*. Например, если вы создаете статическую переменную типа float, у вас не будет проблем с порядком инициализации. Проблема возникает только тогда, когда у вашего статического или глобального объекта есть конструктор. Как бороться с ошибками порядка статической инициализации объектов - членов класса? Предположим, у вас есть класс X, в котором есть статический объект Fred: File X.hpp class X { public: ... private: static Fred x ; Естественно, этот статический член инициализируется отдельно: File X.cpp #include X.hpp Fred X::x ; Опять же естественно, объект Fred будет использован в одном или нескольких методах класса X: void X::someMethod() x .goBowling(); Проблема проявится, если кто-то где-то каким-либо образом вызовет этот метод, до того как объект Fred будет создан. Например, если кто-то создает статический объект X и вызывает его someMethod() во время статической инициализации, то ваша судьба всецело находится в руках компилятора, который либо создаст X::x , до того как будет вызван someMethod(), либо же только после. В любом случае, всегда можно сохранить переносимость (и это абсолютно безопасный метод), заменив статический член X::x на статическую функцию-член: File X.hpp class X { public: ... private: static Fred& x(); Естественно, этот статический член инициализируется отдельно: File X.cpp #include X.hpp Fred& X::x() static Fred* ans = new Fred(); return *ans; После чего вы просто меняете все x на x(): void X::someMethod() x().goBowling(); Если для вас крайне важна скорость работы программы и вас беспокоит необходимость дополнительного вызова функции для каждого вызова X::someMethod(), то вы можете сделать static Fred&. Как вы помните, статические локальные переменные инициализируются только один раз (при первом прохождении программы через их объявление), так что X::x() теперь будет вызвана только один раз: во время первого вызова X::someMethod(): void X::someMethod() static Fred& x = X::x(); x.goBowling(); Примечание: ошибки статической инициализации не распространяются на базовые/встроенные типы, такие как int или char*. Например, если вы создаете статическую переменную типа float, у вас не будет проблем с порядком инициализации. Проблема возникает только тогда, когда у вашего статического или глобального объекта есть конструктор. Как мне обработать ошибку, которая произошла в конструкторе? Сгенерируйте исключение. Что такое деструктор? Деструктор - это исполнение последней воли объекта. Деструкторы используются для высвобождения занятгх объектом ресурсов. Например, класс Lock может заблокировать ресурс для эксклюзивного использования, а его деструктор этот ресурс освободить. Но самый частый случай - это когда в конструкторе используется new, а в деструкторе - delete. Деструктор это функция готовься к смерти . Часто слово деструктор сокращается до dtor. В каком порядке вызываются деструкторы для локальных объектов? В порядке обратном тому, в каком эти объекты создавались: первым создан - последним будет уничтожен.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |