CHAP8_2 (1018809), страница 5

Файл №1018809 CHAP8_2 (Сборник литературы - С и С++) 5 страницаCHAP8_2 (1018809) страница 52017-07-08СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 5)

CDialog::OnOk(); // Послать сообщение базовому классу

else

beep(); // Обычно содержательное сообщение

// Windows об ошибке

}

Функция OnOk() является закрытой в производном классе, потому что никто не будет посылать сообщение OnOk() объекту mydialog. OnOk() базового класса не может быть закрытой, потому что вам нужно образовать цепь с ней из замещения производного класса. Вы не желаете, чтобы CDialog::OnOk() была открытой, потому что снова никто не должен посылать сообщение OnOk() объекту CDialog. Поэтому вы делаете ее защищенной. Теперь замещение из производного класса может образовать цепочку с OnOk(), но эта функция не доступна извне.

Это не очень удачная мысль - использовать защищенный раздел описания класса для обеспечения секретного интерфейса с базовым классом, которым сможет пользоваться лишь производный класс, потому что это может скрыть отношение сцепления. Хотя подобная защищенная функция иногда единственный выход из ситуации, нормальный открытый интерфейс обычно является лучшей альтернативой.

Заметьте, что это правило не имеет обратного действия. Хотя защищенные функции обычно должны быть виртуальными, многие виртуальные функции являются открытыми.

143. Опасайтесь приведения типов (спорные вопросы С++).

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

class base

{

public:

virtual int operator==( const base *&r ) = 0;

};

class derived

{

char *key;

public:

virtual int operator==( const base &r )

{

return strcmp(key, ((const derived &)r).key ) == 0;

}

};

К несчастью, здесь нет гарантии, что передаваемый аргумент r действительно ссылается на объект производного класса. Он не может ссылаться на объект базового класса из-за того, что функция чисто виртуальная: вы не можете создать экземпляр объекта base. Тем не менее, r мог бы быть ссылкой на объект некоего другого класса, унаследованного от base, но не являющегося классом derived. С учетом предыдущего определения следующий код не работает:

class other_derived : public base

{

int key;

// ...

};

f()

{

derived dobj;

other_derived other;

if( derived == other_derived )

id_be_shocked();

}

Комитет ISO/ANSI по С++ рекомендовал механизм преобразования типов во время выполнения, который решает эту проблему, но на момент написания этой книги многие компиляторы его не поддерживают. Предложенный синтаксис выглядит подобным образом:

class derived : public base

{

char *key;

public:

virtual int operator==( const base &r )

{

derived *p = dynamic_cast<derived *>( &r );

return !p ? 0 : strcmp(key, ((const derived &)r).key )==0 ;

}

};

Шаблон функции dynamic_cast<t> возвращает 0, если операнд не может быть безопасно преобразован в тип t, иначе он выполняет преобразование.

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

144. Не вызывайте конструкторов из операции operator=( ).

Хотя это правило говорит о перегруженном присваивании, на самом деле оно посвящено проблеме виртуальных функций. Соблазнительно применить operator=() следующим образом:

class some_class

{

public:

virtual

~some_class( void );

some_class( void );

some_class( const some_class &r );

const some_class &operator=( const some_class &r );

};

const some_class &operator=( const some_class &r )

{

if( this != &r )

{

this->~some_class();

new(this) some_class(r);

}

return *this;

}

Этот вариант оператора new инициализирует указываемый this объект как объект some_class, в данном случае из-за аргумента r используя конструктор копии. 12

Есть серьезные причины не делать показанное выше. Во-первых, это не будет работать после наследования. Если вы определяете:

class derived : public some_class

{

public:

~derived();

// Предположим, что генерированная компилятором операция operator=()

// выполнится за операцией operator=() базового класса.

}

Вследствие того, что деструктор базового класса определен (правильно) как виртуальный, обращение предыдущего базового класса к:

this->~some_class()

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

this->some_class::~some_class();

Явное упоминание имени класса - some_class:: в этом примере - подавляет механизм виртуальной функции. Функция вызывается, как если бы она не была виртуальной.

Деструктор не является единственной проблемой. Рассмотрим простое присваивание объектов производного класса:

derived d1, d2;

d1 = d2;

Операция производного класса operator=() (вне зависимости от того, генерируется она компилятором или нет) образует цепочку с operator=() базового класса, который в настоящем случае использует оператор new() для явного вызова конструктора базового класса. Конструктор, тем не менее, делает значительно больше, чем вы можете видеть в определении. В частности, он инициализирует указатель таблицы виртуальных функций так, чтобы он указывал на таблицу его класса. В текущем примере перед присваиванием указатель vtable указывает на таблицу производного класса. После присваивания указатель vtable указывает на таблицу базового класса; он был переинициализирован неявным вызовом конструктора при вызове new в перегруженной операции operator=().

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

Лучшим способом устранения дублирования кода в операции присваивания operator=() является использование простой вспомогательной функции:

class some_class

{

void create ( void );

void create ( const some_class &r );

void destroy( void );

public:

virtual

~some_class( void ) { destroy(); }

some_class( void ) { create(); }

const some_class &operator=( const some_class &r );

};

inline const some_class &some_class::operator=( const some_class &r )

{

destroy();

create( r );

}

inline some_class::some_class( void )

{

create();

}

~some_class::some_class( void )

{

destroy();

}

10 Книга Эллиса и Страуструпа "The Annotated C++ Reference Manual"(Reading: Addison Wesley,1990), используемая в качестве базового документа комитетом ISO/ANSI по С++.

Имеется перевод на русский язык под редакцией А.Гутмана "Справочное руководство по языку программирования С++ с комментариями"(М.: Мир, 1992). -Прим.перев.

11 Конечно, конструкторы копий и функции operator=(), создаваемые вами (в отличие от компилятора), никогда не вызывают своих двойников из базового класса автоматически.

12 Некоторые компиляторы в действительности позволяют выполнить явный вызов конструктора, поэтому вы, вероятно, сможете сделать точно так же:

const some_class &operator=( const some_class &r )

{

if( this != &r )

{

this->~some_class();

this->some_class::some_class( r );

}

}

Тем не менее, такое поведение является нестандартным.

Характеристики

Тип файла
Документ
Размер
79 Kb
Тип материала
Высшее учебное заведение

Список файлов книги

С и С++ - сборник литературы
C++ Бархатный путь - Марченко А
cpp_001.shtml
cpp_002.shtml
cpp_003.shtml
cpp_004.shtml
cpp_005.shtml
cpp_006.shtml
cpp_007.shtml
cpp_008.shtml
cpp_009.shtml
cpp_010.shtml
cpp_011.shtml
cpp_012.shtml
cpp_013.shtml
cpp_014.shtml
cpp_015.shtml
cpp_016.shtml
cpp_017.shtml
cpp_018.shtml
cpp_019.shtml
cpp_020.shtml
cpp_021.shtml
cpp_022.shtml
cpp_023.shtml
cpp_024.shtml
cpp_025.shtml
cpp_026.shtml
cpp_027.shtml
cpp_030.shtml
cpp_034.shtml
Свежие статьи
Популярно сейчас
Зачем заказывать выполнение своего задания, если оно уже было выполнено много много раз? Его можно просто купить или даже скачать бесплатно на СтудИзбе. Найдите нужный учебный материал у нас!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
7028
Авторов
на СтудИзбе
260
Средний доход
с одного платного файла
Обучение Подробнее