Выбрать главу

■■■

■ Локальные и статические объекты создаются в том порядке, в котором они объявлены в программе.

■ Статические объекты создаются только один раз.

■ Все глобальные объекты создаются до вызова функции main( ).

■ Нет какого-либо определённого порядка создания глобальных объектов.

■ Члены создаются в том порядке, в котором они объявлены внутри класса.

■ Деструкторы вызываются в порядке, обратном порядку вызова конструкторов.

■■■

«Статическая переменная — это переменная, которая является локальной по отношению к функции, но при этом сохраняет своё значение между вызовами функции. Глобальная переменная — это переменная, объявленная вне какой-либо функции.»

[Помни!]

Рассмотрим каждое из приведённых выше правил.

Локальные объекты создаются последовательно...209

Локальные объекты создаются в том порядке, в котором в программе встречаются их объявления. Обычно это порядок появления кода объявлений в функции. ( Если, конечно, в функции нет безусловных переходов, "перепрыгивающих" через объявления. Кстати говоря, безусловные переходы между объявлениями лучше не использовать — это затрудняет чтение и компиляцию программы. )

Статические объекты создаются один раз...209

Статические переменные подобны обычным локальным переменным с тем отличием, что они создаются только один раз. Это очевидно, поскольку статические переменные сохраняют своё значение от вызова к вызову функции. В отличие от С, который может инициализировать статическую переменную в начале программы, С++ дождётся, когда управление перейдёт к строке с объявлением статической переменной, и только тогда начнёт её создание. Разберёмся в приведённой ниже простой программе.

    /* ConstructStatic — демонстрация однократного */

    /*                создания статических объектов */

    #include <cstdio>

    #include <cstdlib>

    #include <iostream>

    using namespace std ;

    class DoNothing

    {

        public :

            DoNothing( int initial )

            {

                cout << "DoNothing сконструирован со значением "

                     << initial

                     << endl ;

            }

    } ;

_________________

209 стр. Глава 17. Аргументация конструирования

    void fn( int i )

    {

        cout << "Функции fn передано значение " << i << endl ;

        static DoNothing dn( i ) ;

    }

    int main( int argcs , char* pArgs[ ] )

    {

        setlocale ( LC_ALL , ".1251" ) ; /* печать кириллицы */

        fn( 10 ) ;

        fn( 20 ) ;

        /* Пауза для того, чтобы посмотреть на результат работы программы */

        system( "PAUSE" ) ; return 0 ;

    }

После запуска этой программы на экране появится следующее:

Функции fn передано значение 10

DoNothing сконструирован со значением 10

Функции fn передано значение 20

Press any key to continue...

Обратите внимание, что сообщение от функции fn( ) появилось дважды, а сообщение от конструктора DoNothing — только при первом вызове fn( ).

Все глобальные объекты создаются до вызова main( )...210

Все глобальные объекты входят в область видимости программы. Таким образом, все они конструируются до того, как управление передаётся функции main( ).

«При отладке такой порядок может привести к неприятностям. Некоторые отладчики пытаются выполнить весь код, который находится до main( ), и только потом передать управление пользователю. Это прекрасно подходит для С, поскольку до входа в функцию main( ) там не может быть никакого кода, написанного пользователем. Однако в С++ это может стать причиной большой головной боли, поскольку тела конструкторов для всех глобальных объектов к моменту передачи управления main( ) уже выполнены. Если хоть один из этих конструкторов содержит серьёзный "жучок", программа погибнет до того, как начнёт выполняться!»