Алгоритмические языки и программирование. Викентьева О.Л - 17 стр.

UptoLike

17
следует всегда явно определять конструктор копирования и опе-
рацию присваивания, выполняющие выделение памяти под динамиче-
ские поля объекта.
Динамическая память, выделенная в конструкторе объекта, должна
освобождаться в его деструкторе. Невыполнение этого требования
приводит к утечкам памяти. Удаление нулевого указателя безо-
пасно (при этом ничего не происходит), поэтому если конструк-
торы, конструкторы копирования и операция присваивания написа-
ны правильно, любой указатель либо ссылается на выделенную об-
ласть памяти, либо равен нулю, и к нему можно применять delete
без проверки.
Разница между конструктором копирования и операцией присваива-
ния заключается в том, что последняя работает в том случае,
когда объект-приемник уже существует, поэтому в ней перед вы-
делением динамической памяти следует освободить память занятую
ранее. Из этого следует, что при реализации операции при-
сваивания для классов, содержащих поля-указатели, необходимо
проводить проверку на самоприсваивание и в этом случае оста-
вить объект без изменений. Необходимо также помнить о том, что
операция присваивания должна возвращать ссылку на константу.
В конструкторах для задания начальных значений полям рекомен-
дуется использовать инициализацию, а не присваивание. Инициа-
лизация более универсальна, так как может применяться в тех
случаях, когда присваиванием пользоваться нельзя (например,
при задании значений константным полям или ссылкам). Кроме то-
го, она выполняется более эффективно, потому что создание объ-
екта в C++ начинается с инициализации его полей конструктором
по умолчанию, после чего выполняется вызываемый конструктор.
Необходимо учитывать и тот факт, что поля инициализируются в
порядке их объявления, а не в порядке появления в списке ини-
циализации. Поэтому для уменьшения числа возможных ошибок по-
рядок указания полей в списке инициализации
конструктора дол-
жен соответствовать порядку их объявления в классе.
Статические поля не должны инициализироваться в конструкторе,
поскольку им нужно присваивать начальное значение только один
раз для каждого класса, а конструктор выполняется для каждого
объекта класса. Статические поля инициализируются в глобальной
области определения (вне любой функции).
Конструкторы копирования также должны использовать списки ини-
циализации полей, поскольку иначе для базовых классов и вло-
женных объектов будут вызваны конструкторы по умолчанию.
Операция присваивания не наследуется, поэтому она должна быть
определена в производных классах. При этом из нее следует яв-
ным образом вызывать соответствующую операцию базового класса
Открытое наследование класса Y из
класса X означает, что Y
представляет собой разновидность класса X, то есть более кон-
кретную, частную концепцию. Базовый класс X является более об-
щим понятием, чем Y. Везде, где можно использовать X, можно
использовать и Y, но не наоборот (вспомните, что на место ссы-
лок на базовый класс можно передавать ссылку на любой из про-
изводных). Необходимо помнить, что во время выполнения про-
граммы не существует иерархии классов и передачи сообщений
                                                                17

    следует всегда явно определять конструктор копирования и опе-
    рацию присваивания, выполняющие выделение памяти под динамиче-
    ские поля объекта.
•   Динамическая память, выделенная в конструкторе объекта, должна
    освобождаться в его деструкторе. Невыполнение этого требования
    приводит к утечкам памяти. Удаление нулевого указателя безо-
    пасно (при этом ничего не происходит), поэтому если конструк-
    торы, конструкторы копирования и операция присваивания написа-
    ны правильно, любой указатель либо ссылается на выделенную об-
    ласть памяти, либо равен нулю, и к нему можно применять delete
    без проверки.
•   Разница между конструктором копирования и операцией присваива-
    ния заключается в том, что последняя работает в том случае,
    когда объект-приемник уже существует, поэтому в ней перед вы-
    делением динамической памяти следует освободить память занятую
    ранее. Из этого следует, что при реализации операции при-
    сваивания для классов, содержащих поля-указатели, необходимо
    проводить проверку на самоприсваивание и в этом случае оста-
    вить объект без изменений. Необходимо также помнить о том, что
    операция присваивания должна возвращать ссылку на константу.
•   В конструкторах для задания начальных значений полям рекомен-
    дуется использовать инициализацию, а не присваивание. Инициа-
    лизация более универсальна, так как может применяться в тех
    случаях, когда присваиванием пользоваться нельзя (например,
    при задании значений константным полям или ссылкам). Кроме то-
    го, она выполняется более эффективно, потому что создание объ-
    екта в C++ начинается с инициализации его полей конструктором
    по умолчанию, после чего выполняется вызываемый конструктор.
    Необходимо учитывать и тот факт, что поля инициализируются в
    порядке их объявления, а не в порядке появления в списке ини-
    циализации. Поэтому для уменьшения числа возможных ошибок по-
    рядок указания полей в списке инициализации конструктора дол-
    жен соответствовать порядку их объявления в классе.
•   Статические поля не должны инициализироваться в конструкторе,
    поскольку им нужно присваивать начальное значение только один
    раз для каждого класса, а конструктор выполняется для каждого
    объекта класса. Статические поля инициализируются в глобальной
    области определения (вне любой функции).
•   Конструкторы копирования также должны использовать списки ини-
    циализации полей, поскольку иначе для базовых классов и вло-
    женных объектов будут вызваны конструкторы по умолчанию.
•   Операция присваивания не наследуется, поэтому она должна быть
    определена в производных классах. При этом из нее следует яв-
    ным образом вызывать соответствующую операцию базового класса
•   Открытое наследование класса Y из класса X означает, что Y
    представляет собой разновидность класса X, то есть более кон-
    кретную, частную концепцию. Базовый класс X является более об-
    щим понятием, чем Y. Везде, где можно использовать X, можно
    использовать и Y, но не наоборот (вспомните, что на место ссы-
    лок на базовый класс можно передавать ссылку на любой из про-
    изводных). Необходимо помнить, что во время выполнения про-
    граммы не существует иерархии классов и передачи сообщений