Скотт Майерс - Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ

Тут можно читать онлайн Скотт Майерс - Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ - бесплатно ознакомительный отрывок. Жанр: comp-programming, издательство Литагент «ДМК»233a80b4-1212-102e-b479-a360f6b39df7, год 2006. Здесь Вы можете читать ознакомительный отрывок из книги онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ
  • Автор:
  • Жанр:
  • Издательство:
    Литагент «ДМК»233a80b4-1212-102e-b479-a360f6b39df7
  • Год:
    2006
  • Город:
    Москва
  • ISBN:
    5-94074-304-8
  • Рейтинг:
    3.6/5. Голосов: 101
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

Скотт Майерс - Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ краткое содержание

Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ - описание и краткое содержание, автор Скотт Майерс, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

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

Издание ориентировано на программистов, знакомых с основами C++ и имеющих навыки его практического применения.

Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ - читать онлайн бесплатно ознакомительный отрывок

Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ - читать книгу онлайн бесплатно (ознакомительный отрывок), автор Скотт Майерс
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

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

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

class Timer {

public:

explicit Timer(int tickFrequency);

virtual void onTick() const; // автоматически вызывается

// при каждом тике

...

};

Это как раз то, что мы искали. Объект Timer можно настроить для срабатывания с любой частотой, и при каждом «тике» будет вызываться виртуальная функция. Мы можем переопределить эту виртуальную функцию так, чтобы она проверяла текущее состояние Widget. Отлично!

Для того чтобы класс Widget переопределял виртуальную функцию Timer, он должен наследовать Timer. Но открытое наследование в данном случае не подходит. Ведь Widget не является разновидностью Timer. Пользователи Widget не должны иметь возможности вызывать onTick для объекта Widget, потому что эта функция не является частью концептуального интерфейса этого класса. Если разрешить вызов подобной функции, то пользователи получат возможность работать с интерфейсом Widget некорректно, что очевидно нарушает рекомендацию из правила 18 о том, что интерфейсы должно быть легко применять правильно и трудно – неправильно. Открытое наследование в данном случае не подходит.

Потому мы будем наследовать закрыто:

class Widget: private Timer {

private:

virtual void onTick() const; // просмотр данных об использовании

... // Widget и т. п.

};

Благодаря закрытому наследованию открытая функция onTick класса Timer становится закрытой в Widget, и после переопределения мы ее такой и оставим. Опять же, если поместить onTick в секцию public, то это введет в заблуждение пользователей, заставляя их думать, будто ее можно вызвать, а это идет вразрез с правилом 18.

Это неплохое решение, но стоит отметить, что закрытое наследование не является здесь строго необходимым. Никто не мешает вместо него использовать композицию. Мы просто объявим закрытый вложенный класс внутри Widget, который будет открыто наследовать классу Timer и переопределять onTick, а затем поместим объект этого типа внутрь Widget. Вот эскиз такого подхода:

class Widget private class WidgetTimer public Timer public - фото 9

class Widget {

private:

class WidgetTimer: public Timer {

public:

virtual void onTick() const;

...

};

WidgetTimer timer;

...

};

Этот дизайн сложнее того, что использует только закрытое наследование, потому что здесь используются и открытое наследование, и композиция, а ко всему еще и новый класс (WidgetTimer). Честно говоря, я показал этот вариант в первую очередь для того, чтобы напомнить о существовании различных подходов к решению одной задачи. Стоит привыкать к тому, чтобы не ограничиваться единственным решением (см. также правило 35). Тем не менее я могу представить две причины, по которым иногда имеет смысл предпочесть открытое наследование в сочетании с композицией закрытому наследованию.

Во-первых, вы можете спроектировать класс Widget так, чтобы ему можно было наследовать, но при этом запретить производным классам переопределять функцию onTick. Если Widget наследуется от Timer, то это невозможно, даже в случае закрытого наследования. (Напомню, что согласно правилу 35 производные классы могут переопределять виртуальные функции, даже если не могут вызывать их). Но если WidgetTimer – это закрытый класс внутри Widget, который наследует Timer, то производные от Widget классы не имеют доступа к WidgetTimer, а значит, не могут ни наследовать ему, ни переопределять его виртуальные функции. Если вам приходилось программировать на языках Java или C# и вы не обратили внимания на то, как можно запретить производным классам переопределять функции базового (с помощью ключевого слова final в Java или sealed в C#), то теперь вы знаете, как добиться примерно того же эффекта в C++.

Во-вторых, вы можете захотеть минимизировать зависимости Widget на этапе компиляции. Если Widget наследует классу Timer, то определение Timer должно быть доступно во время компиляции Widget, поэтому файл, определяющий Widget, вероятно, должен содержать директиву #include "Timer.h". С другой стороны, если WidgetTimer вынести из Widget, а в Widget оставить только указатель на WidgetTimer, тогда Widget сможет обойтись простым объявлением класса WidgetTimer; так что необходимость включать заголовочный файл для Timer будет устранена. Для больших систем такая развязка может оказаться важной. Подробнее о минимизации зависимостей на этапе компиляциии см. правило 31.

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

Граничный случай – действительно граничный: речь идет о классах, в которых вообще нет никаких данных. Такие классы не имеют ни нестатических членов-данных, ни виртуальных функций (поскольку наличие этих функций означает добавление указателя vptr в каждый объект – см. правило 7), ни виртуальных базовых классов (поскольку в этом случае тоже имеют место дополнительные расходы памяти – см. правило 40). Концептуально, объекты таких пустых классов вообще не занимают места, потому что в них не хранится никаких данных. Однако есть технические причины, по которым C++ требует, чтобы любой автономный объект должен иметь ненулевой размер, поэтому для следующих объявлений:

class Empty {}; // не имеет данных, поэтому объекты

// не должны занимать памяти

class HoldsAnInt { // память, по идее, нужна только для int

private:

int x;

Empty e; // не должен занимать память

};

оказывается, что sizeof(HoldsAnlnt) > sizeof(int); член данных Empty занимает какую-то память. Для большинства компиляторов sizeof(Empty) будет равно 1, потому что требование C++ о том, что не должно быть объектов нулевой длины, обычно удовлетворяется молчаливой вставкой одного байта (char) в такой «пустой» объект. Однако из-за необходимости выравнивания (см. правило 50) компилятор может оказаться вынужден дополнить классы, подобные HoldsAnInt, поэтому вполне вероятно, что размер объектов HoldsAnInt увеличится больше чем на char, скорее всего, речь может идти о росте на размер int. На всех компиляторах, где я тестировал, происходило именно так.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


Скотт Майерс читать все книги автора по порядку

Скотт Майерс - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки LibKing.




Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ отзывы


Отзывы читателей о книге Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ, автор: Скотт Майерс. Читайте комментарии и мнения людей о произведении.


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x