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

Здесь есть возможность читать онлайн «Скотт Майерс - Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ» — ознакомительный отрывок электронной книги совершенно бесплатно, а после прочтения отрывка купить полную версию. В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Город: Москва, Год выпуска: 2006, ISBN: 2006, Издательство: Array Литагент «ДМК», Жанр: Программирование, на русском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

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

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

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

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

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Я использую приведение в старом стиле только тогда, когда хочу вызвать explicit конструктор, чтобы передать объект в качестве параметра функции. Например:

class Widget {

public:

explicit Widget(int size);

...

};

void doSomeWork(const Widget& w);

doSomeWork(Widget(15)); // создать Widget из int

// с функциональным приведением

doSomeWork(static_cast(15)); // создать Widget из int

// с приведением в стиле C++

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

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

int x, y;

...

double d = static_cast(x)/y; // деление x на y с использованием

// деления с плавающей точкой

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

class Base {...};

class Derived: public Base {...};

Derived d;

Base *pb = &d; // неявное преобразование Derived*

// в Base*

Здесь мы всего лишь создали указатель базового класса на объект производного, но иногдаэти два указателя указывают вовсе не на одно и то же. В таком случае во время исполнения к указателю Derived* прибавляется смещение, чтобы получить правильное значение указателя Base*.

Последний пример демонстрирует, что один и тот же объект (например, объект типа Derived) может иметь более одного адреса (например, адрес при указании на него как на Base* отличается от адреса при указании как на Derived*). Такое невозможно в C. Такое невозможно в Java. Такого не бывает в C#. Но это случается в C++. Фактически, когда применяется множественное наследование, такое случается сплошь и рядом, но может произойти и при одиночном наследовании. Это ко всему прочему означает, что, программируя на C++, вы не должны строить предположений о том, как объекты располагаются в памяти, и уж тем более не должны выполнять приведение типов на базе этих предположений. Например, приведение адреса объекта к типу char* и последующее использование арифметических операций над указателями почти всегда становятся причиной неопределенного поведения.

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

Интересный момент, касающийся приведений, – еще в том, что легко написать код, который выглядит правильным (и может быть правильным на других языках), но на самом деле правильным не является. Например, во многих каркасах для разработки приложений требуется, чтобы виртуальные функции-члены, определенные в производных классах, вначале вызывали соответствующие функции из базовых классов. Предположим, что у нас есть базовый класс Window и производный от него класс SpecialWindow, причем в обоих определена виртуальная функция onResize. Далее предположим, что onResize из SpecialWindow будет вызывать сначала onResize из Window. Следующая реализация выглядит хорошо, но по сути неправильна:

class Window { // базовый класс

public:

virtual void onResize() {...} // реализация onResize в базовом

... // классе

};

class SpecialWindow: public Window { // производный класс

public:

virtual void onResize() { // реализация onResize

static_cast(*this).onResize(); // в производном классе;

// приведение *this к Window,

// затем вызов его onResize;

// это не работает!

... // выполнение специфической для

} // SpecialWindow части onResize

...

};

Я выделил в этом коде приведение типа. (Это приведение в новом стиле, но использование старого стиля ничего не меняет.) Как и ожидается, *this приводит к типу Window. Поэтому обращение к onResize приводит к вызову Window::onResize. Вот только эта функция не будет вызвана для текущего объекта! Неожиданно, не правда ли? Вместо этого оператор приведения создаст новую, временную копию части базового класса *this и вызовет onResize для этой копии! Приведенный выше код не вызовет Window::onResize для текущего объекта с последующим выполнением специфичных для SpecialWindow действий – он выполнит Window::onResize для копии части базового класса текущего объекта перед выполнением специфичных для SpecialWindow действий для данного объекта. Если Window::onResize модифицирует объект (что вполне возможно, так как onResize – не константная функция-член), то текущий объект не будет модифицирован. Вместо этого будет модифицирована копия этого объекта. Однако если SpecialWindow::onResize модифицирует объект, то будет модифицирован именно текущий объект. И в результате текущий объект остается в несогласованном состоянии, потому что модификация той его части, что принадлежит базовому классу, не будет выполнена, а модификация части, принадлежащей производному классу, будет.

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

Интервал:

Закладка:

Сделать

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

Представляем Вашему вниманию похожие книги на «Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


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

Обсуждение, отзывы о книге «Эффективное использование C++. 55 верных способов улучшить структуру и код ваших программ» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x