Программирование >>  Аргументация конструирования 

1 ... 59 60 61 [ 62 ] 63 64 65 ... 108



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

объектов к моменту передачи управления main() уже выполнены. Если хоть один из этих конструкторов содержит серьезный жучок , программа

погибнет до того, как начнет выполняться!

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

увидите, вероятно, будет сообщением конструктора с ошибкой.

Порядок создания глобальных объектов не определен

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

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

компилятору не начать с начала файла с исходной программой и не создавать глобальные объекты в порядке их объявления? (Честно говоря, я подозреваю, что на самом деле

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

Однако большинство программ в реальном мире состоят из нескольких файлов, которые компилируются каждый в отдельности, а уже затем связываются в единое целое. Поскольку компилятор не управляет порядком связывания, он не может влиять

на порядок вызова конструкторов глобальных объектов в разных файлах.

В принципе в большинстве случаев порядок создания глобальных объектов не так уж

и важен. Тем не менее иногда это может привести к ошибкам, которые потом очень сложно отследить (такое случается довольно часто, чтобы обратить на это внимание в книге).

Разберем приведенный ниже пример. в файле Student.Н:

class Student

public:

Student (unsigned id) : studentld(id)

const unsigned Studentld;

class Tutor {

public;

Tutor (Students s) {

tutoredid = E.studentld;

protected:

tutoredld;

b файле FILEl.CPP Создаем студента




Student randy(123 4) ;

в файле FILE2.CPP Назначаем студенту учителя Tutor jenny(randy);

В этом примере конструктор student присваивает студенту идентификатор, а конструктор класса Tutor записывает этот идентификатор студента, которому нужен учитель. Программа объявляет студента randy, а затем назначает ему учителя jenny.

При этом подразумевается, что randy создается раньше, чем jenny; в этом-то и состоит проблема. Представьте себе, что порядок создания этих объектов будет другим. Тогда объект jenny будет построен с использованием блока памяти, который пока что не является объектом типа student, а значит, вместо идентификатора студента в randy будет находиться непредсказуемое значение.

Приведенный выше пример несложен и несколько надуман. Однако проблемы, создаваемые глобальными объектами, могут оказаться гораздо коварнее. Во избежание этого не допускайте, чтобы конструктор глобального объекта обращался к другому глобальному объекту.

Члены создаются в порядке их объявления

Члены класса создаются в соответствии с порядком, в котором они объявлены внутри класса. Это не так просто и очевидно, как может показаться на первый взгляд. Рассмотрим пример.

class Student

public:

Student (unsigned id, unsigned age) : sAge(age), sld(id)

const unsigned sId;

const unsigned sAge;

В этом примера s Id создается до sAge, несмотря на то что он стоит вторым в инициализирующем списке конструктора. Впрочем, единственный случай, когда можно заметить какую-то разницу в порядке конструирования, - это когда оба члена

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

В каком бы порядке не вызывались конструкторы объектов, вы можете быть уверены, что их деструкторы будут вызваны в обратном порядке. (Приятно сознавать, что

хоть одно правило в C++ не имеет никаких или , и либо но )



Глава19

Копирующий конструктор

в э>ной главе...

Копирование объекта

у Автоматический конструктор копирования У Мелкие и глубокие копии У Времеппые объекты

опструктор - это специальная функция, которая автоматически вызывается # V/ С++ при создании объекта с тем, чтобы предоставить ему возможность про-инициализировать самого себя. В главе 17, Создание и удаление объектов: конструктор и деструктор , описаны концепции применения конструкторов, в главе 18, Аргументация конструирования , вы познакомились с разными типами конструкторов. А в настоящей главе рассматривается частный случай, известный под названием копирующего конструктора (или конструктора копирования).

Конструктор, который используется C++ для создания копий объекта, называется копирующим конструктором. Он имеет вид (xs) (или x::X(cons )), где X - имя класса. Да, это не ошибка - это действительно конструктор класса х, который требует в качестве аргумента ссылку на объект класса X. Я понимаю, что это звучит несколько бессмысленно, но не торопитесь с выводами и позвольте объяснить, зачем такое в C++.

Зачем это нужно

Подумайте о том, что будет происходить в программе, если вы вызовете следующую функцию: voi udent fs) {

тот же сценарий с другими аргументами

in t argcs, char* pArgs [ ] )

Student return 0;

При вызове описанной функции fn () ей будет передан в качестве аргумента не сам объект, а его копия.

Теперь попробуем понять, что же значит - создать копию объекта. Для этого требуется конструктор, который будет создавать объект (даже если копируется уже существующий объект). C++ мог бы побайтово скопировать существующий объект в но-



1 ... 59 60 61 [ 62 ] 63 64 65 ... 108

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика