Скотт Майерс - Эффективное использование 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 верных способов улучшить структуру и код ваших программ - читать книгу онлайн бесплатно (ознакомительный отрывок), автор Скотт Майерс
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Это можно сделать с помощью using-объявлений:

class Base private int x public virtual void mf1 0 virtual - фото 6

class Base {

private:

int x;

public:

virtual void mf1() = 0;

virtual void mf1(int);

virtual void mf2();

void mf3();

void mf3(double);

...

};

class Derived: public Base {

public:

using Base::mf1; // обеспечить видимость всех (открытых) имен

using Base::mf3; // mf1 и mf3 из класса Base в классе Derived

virtual void mf1()

void mf3();

void mf4();

...

};

Теперь наследование будет работать, как и ожидается.

Derived d;

int x;

...

d.mf1(); // по-прежнему правильно, вызывается Derived::mf1

d.mf1(x); // теперь правильно, вызывается Base::mf1

d.mf2(); // по-прежнему правильно, вызывается Base::mf2

d.mf3(); // по-прежнему правильно, вызывается Derived::mf3

d.mf3(x); // теперь правильно, вызывается Base::mf3

Это означает, что если вы наследуете базовому классу с перегруженными функциями и хотите переопределить только некоторые из них, то должны включить using-объявление для каждого имени, иначе оно будет скрыто.

Можно представить себе ситуацию, когда вы не хотите наследовать все функции из базовых классов. При открытом наследовании такое никогда не должно происходить, так как это противоречит смыслу отношения «является» между базовым классом и производным от него. Вот почему using-объявление находится в секции public объявления производного класса; имена, которые открыты в базовом классе, должны оставаться открытыми и в открыто унаследованном от него. Но при закрытом наследовании (см. правило 39) такое желание иногда осмыслено. Например, предположим, что класс Derived закрыто наследует классу Base, и единственная версия mfl, которую Derived хочет унаследовать, – это та, что не принимает параметров. Using-объявление в этом случае не поможет, поскольку оно делает видимыми в производном классе все унаследованные функции с заданным именем. Здесь требуется другая техника – простая перенаправляющая функция:

class Base {

public:

virtual void mf1() = 0;

virtual void mf1(int);

... // как раньше

};

class Derived: private Base {

public:

virtual void mf1() // перенаправляющая функция

{ Base::mf1();} // неявно встроена (см. правило 30)

...

};

...

Derived d;

Int x;

d.mf1(); // правильно, вызывается Derived::mf1

d.mf1(x); // ошибка! Base::mf1 скрыта

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

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

Что следует помнить

• Имена в производных классах скрывают имена из базовых классов. При открытом наследовании это всегда нежелательно.

• Чтобы сделать скрытые имена видимыми, используйте using-объявления либо перенаправляющие функции.

Правило 34: Различайте наследование интерфейса и наследование реализации

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

При разработке классов иногда требуется, чтобы производные классы наследовали только интерфейс (объявления) функций-членов. В других случаях необходимо, чтобы производные классы наследовали и интерфейс, и реализацию функций, но могли переопределять унаследованную реализацию. А иногда вам может понадобиться использование наследования интерфейса и реализации, но без возможности что-либо переопределять.

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

class Shape {

public:

virtual void draw() const = 0;

virtual void error(const std::string& msg);

int objectID() const;

...

};

class Rectangle: public Shape {…};

class Ellipse: public Shape {…};

Shape – это абстрактный класс; таковым его делает чисто виртуальная функция draw. В результате пользователи не могут создавать объекты класса Shape, а лишь классов, производных от него. Несмотря на это, Shape оказывает сильное влияние на все открыто наследующие ему классы по следующей причине:

• Интерфейс функций-членов наследуется всегда. Как объясняется в правиле 32, открытое наследование означает «является», поэтому все, что верно для базового класса, также верно и для производных от него. Поэтому если функция применима к классу, она остается применимой и для подклассов.

В классе Shape объявлены три функции. Первая, draw, выводит текущий объект на дисплей, подразумеваемый по умолчанию. Вторая, error, вызывается функциями-членами, если необходимо сообщить об ошибке. Третья, objectID, возвращает уникальный целочисленный идентификатор текущего объекта. Каждая из трех функций объявлена по-разному: draw – как чисто виртуальная; error – как просто виртуальная; а objectID – как невиртуальная функция. Каковы практические последствия этих различий?

Рассмотрим первую чисто виртуальную функцию draw:

class Shape {

public:

virtual void draw() const = 0;

...

};

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

• Цель объявления чисто виртуальной функции состоит в том, чтобы производные классы наследовали только ее интерфейс.

Это в полной мере относится к функции Shape::draw, поскольку наиболее разумное требование ко всем объектам класса Shape заключается в том, что они должны быть отображены на дисплее, но Shape не может обеспечить разумной реализации этой функции по умолчанию. Алгоритм рисования эллипса очень сильно отличается от алгоритма рисования прямоугольника. Объявление Shape::draw можно интерпретировать как следующее сообщение разработчикам конкретных подклассов: «Вы должны обеспечить наличие функции draw, но у меня нет ни малейшего представления, как вы это собираетесь сделать».

Между прочим, дать определение чисто виртуальной функции возможно. Иными словами, вы можете предоставить реализацию для Shape::draw, и С++ будет ее компилировать, но единственный способ вызвать – квалифицировать имя функции названием класса:

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

Интервал:

Закладка:

Сделать


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

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




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


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


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

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