Albert Makhmutov - Идиомы и стили С++
Название: | Идиомы и стили С++ | |
Автор: | Albert Makhmutov | |
Жанр: | Современные российские издания, Литература ХXI века (эпоха Глобализации экономики), Программирование: прочее, C, C++, C# | |
Изадано в серии: | неизвестно | |
Издательство: | неизвестно | |
Год издания: | - | |
ISBN: | неизвестно | |
Отзывы: | Комментировать | |
Рейтинг: | ||
Поделись книгой с друзьями! Помощь сайту: донат на оплату сервера |
Краткое содержание книги "Идиомы и стили С++"
Аннотация к этой книге отсутствует.
Читаем онлайн "Идиомы и стили С++". [Страница - 2]
- 1
- 2
- 3
- 4
- . . .
- последняя (24) »
5. Буч, Гради. Объектно-ориентированное проектирование с примерами на С++. Второе издание.
6. Бабе, Бруно. Все о С++.
7. Microsoft corp. Официальное пособие по разработке приложений на VC++6.0
Вообще говоря, в основном все буду брать у Элджера. Проще, и интереснее. Мы же не умереть собираемся.
Ну и все. Начнем, пожалуй.
Шаг 2 - Умные указатели.
Сначала договоримся о терминах. Перегрузка функций (overloading) - многократное определение функции с разным набором аргументов (сигнатурой). В сигнатуру включается модификатор const, но не включается возвращаемое значение. Перегрузка операторов (overloading) - то же самое (операторы это собственно функции, только имя у них предопределенное), ПЛЮС само определение такого оператора. Если вы определили оператор для какого-то класса, это уже считается перегрузкой. Переопределение функций (overriding) - определение функций в субклассах с тем же именем. Правила переопределения функций достаточно сложны, и я не хотел бы грузить вас ими. Скажу только, что в Object Pascal они не в пример яснее, и компилятор укажет вам, что вы тормоз, если тормознете. А в Плюсах компилятор просто скроет функции, которые вы переопределите неправильно. Ну мы ему отомстим.В C++ мы можем перегрузить почти все операторы, за исключением нескольких. Во всяком случае, оператор -› перегружается, и это имеет значение крайне важное. Кстати, он называется селектором (member selector). Итак, попробуем:
#include ‹mem.h›
class Cthat {
public:
void doIt(void){return;};
};
class CPthat {
private:
Cthat* aThat;
public:
CPthat(Cthat* _that=NULL):aThat(_that){}
~CPthat() { if (aThat) delete aThat; }
operator Cthat* () { return aThat;} // Оператор преобразования типа
CThat* operator-›() { return aThat; }; // Оператор селектора -›
CPthat operator+(ptrdiff_t _offset) { return CPthat(aThat+_offset); }
// ^^^^^^^^^
};
int main () {
Cthat* aThat = new Cthat;
aThat-›doSomething();
CPthat pthat(new Cthat);
pthat-›doIt(); // Вариант обращения через -›
((Cthat*)pthat)-›doIt (); //Вариант обращения через Cthat*
delete aThat;
return 0;
}
Что получилось: Имеем класс Cthat, который может иметь экземпляры, хотя и не имеет наполнения, и может исполнить пустую функцию. (Обратите внимание. Пустой объект имеет размер 1, и если добавить переменную char, то размер будет тот же. Экземпляры пустых объектов существуют, и они различаются.) Имеем класс объекта-указателя CPthat, в котором храним обычный указатель, но доступ к нему ограничиваем, и перегружаем для него операторы:
1. приведения типа Cthat
2. member selector -›.
3. Операторы арифметики указателей. Я указал только один, сложение.
Идея ясная. Нужно переопределить все восемь, или не переопределять их вовсе. Вопрос в том, направлен ли Ваш указатель на массив, или нет. Во всяком случае, не спешите с этим. Да, и в Ваших плюсах скорее всего тип ptrdiff_t надо заменить на ptr_diff. Я просто дома на BC3.1 все проверяю.
Что здесь хорошего? Мы получили класс объектов-указателей, которые можно смело применять вместо настоящих. Деструктор ~CPthat() уничтожает указуемый объект, поскольку сам по себе последний не имеет имени, и без своего указателя утрачивает идентичность. Проще говоря, останется в нашей памяти навечно, как герой. Ну можно конечно вызывать деструктор и явно, а что? Вот так:
pthat-›~Cthat();
Тогда удаление уберите из деструктора указателя.
Напоследок сделаем очевидный шаг - сделаем умный указатель параметризированным классом.
template ‹class T›
class SmartPointer {
private:
T* tObj;
public:
SmartPointer(T* _t=NULL):tObj(_t);
~SmartPointer(){ if (tObj) delete tObj; }
operator T*(){ return tObj; }
T* operator-›(){ return tObj; }
};
Для интереса посмотрите, как сделан auto_ptr в STL.
Передохнем. Кофе. Джоггинг. Пиво. Сигарета. Нужное подчеркнуть, выпить, покурить.
Шаг 3 - Как это применять.
Берем код параметризированного класса.template ‹class T›
class SmartPointer {
private:
T* tObj;
public:
SmartPointer(T* _t=NULL): tObj(_t);
~SmartPointer() {if (tObj) delete tObj;}
operator T*(){return tObj;}
T* operator-›(){return tObj;}
};
1. Обработка обращения к NULL.
Заменяем реализацию оператора -› на:T* operator-›() {
if (!tObj) {
cerr ‹‹ "NULL";
tObj = new T;
}
return tObj;
}
или
T* operator-›() {
if (!tObj) throw CError;
return tObj;
};
Здесь CError класс исключения. Или втыкаем статический экземпляр-шпион.
private:
T* tObj; // Это было;
static T* spy; // Это добавлено
Ну и сам перегруженный --">- 1
- 2
- 3
- 4
- . . .
- последняя (24) »
Книги схожие с «Идиомы и стили С++» по жанру, серии, автору или названию:
Джамиль Зайнашефф - Классика пивоварения. Все стили и виды пива от эля до лагера Жанр: Виноделие, спиртные напитки Год издания: 2018 |
Олег Брылев - Афганская ловушка Жанр: Новейшая история Год издания: 2014 |