Albert Makhmutov - Идиомы и стили С++

Тут можно читать онлайн Albert Makhmutov - Идиомы и стили С++ - бесплатно полную версию книги (целиком) без сокращений. Жанр: comp-programming. Здесь Вы можете читать полную версию (весь текст) онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    Идиомы и стили С++
  • Автор:
  • Жанр:
  • Издательство:
    неизвестно
  • Год:
    неизвестен
  • ISBN:
    нет данных
  • Рейтинг:
    4.13/5. Голосов: 81
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

Albert Makhmutov - Идиомы и стили С++ краткое содержание

Идиомы и стили С++ - описание и краткое содержание, автор Albert Makhmutov, читайте бесплатно онлайн на сайте электронной библиотеки LibKing.Ru

Идиомы и стили С++ - читать онлайн бесплатно полную версию (весь текст целиком)

Идиомы и стили С++ - читать книгу онлайн бесплатно, автор Albert Makhmutov
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Код ниже, а сейчас пояснения:

Класс CTypeпросто проверочный, чтобы вкладывать в шаблоны; так проще отлаживать шаблон: сначала сделать контейнер-не-шаблон для класса Type, а потом просто приписать сверху объявления строку template‹Type›. Шаблон класса ampstack‹Type›- шаблон стека указателей; pushсохраняет указатель, popдостает верхний указатель, isEmptyпроверяет на пустоту, emptyAllочищает.

Шаблон класса MLTrans- наконец тот, который нам нужен. Указатель thatхранит текущее значение, Pushсохраняет текущее значение, PopOneделает однократную отмену, Rollbackотменяет все изменения, до первоначального, Commitудаляет историю.

// Это маленький класс для проверки

class CType {

int a;

public:

void set (int _a) { a=_a; }

int get (void) { return a; }

};

// Шаблон стека

template ‹class Type›

class ampstack {

private:

int iTop; // верх стека

int iSize; // размер стека

Type** array; // массив указателей

public:

// Конструктор-деструктор

ampstack(int size=10) : iTop(0), iSize(size), array(new Type*[size]) {}

~ampstack() {

for (int iCounter = 0; iCounter ‹ iTop; iCounter ++)

if (*(array+iCounter)!= NULL) delete *(array+iCounter);

delete[] array;

}

// Управление стеком

// Направить указатель в стек

void push (Type* _t) { array[iTop++]=_t; }

// Вынуть указатель из стека

Type* pop (void) {

if (iTop == 0) return NULL;

else return array[--iTop];

}

// Стек пуст?

int isEmpty (void) { return iTop==0; }

// Очистить стек

void emptyAll (void) {

for (int iCounter = 0; iCounter ‹ iTop; iCounter ++)

if (*(array+iCounter)!= NULL) delete *(array+iCounter);

iTop = 0;

}

};

// Шаблон класса с многоуровневой отменой

template ‹class Type›

class MLTrans {

typedef ampstack‹Type› stack;

private:

Type* that; // Текущее значение

stack history; // контейнер предыдущих значений

public:

// конструктор-деструктор

MLTrans(): that(new Type) {}

~MLTrans () { delete that; }

// Сохранение текущего значения, aналог SAVE TRANSACTIONв SQLсерверах

void Push() {

history.push(that);

that = new Type(*that);

}

// удаление промежуточных состояний

void Commit () { history.emptyAll(); }

// Откат на одну позицию; уничтожает текущее значение.

void PopOne() {

if (!history.isEmpty()) {

delete that;

that = history.pop();

}

}

// Откат к началу транзакции.

void Rollback() {

Type* old = history.pop();

Type* older = NULL;

if (old!= NULL) {

while ((older = history.pop())!= NULL) {

delete old;

old = older;

}

delete that;

that = old;

}

}

// Переопределенный operator-›

Type* operator-›() { return that; }

}

// проверим работу

int main() {

int t;

MLTrans‹CType› a;

a-›set(5);

t = a-›get();

a.Push();

a-›set(6);

t = a-›get();

a.Push();

t = a-›get();

a-›set(7);

t = a-›get();

a.Push();

t = a-›get();

a-›set(9);

t = a-›get();

// a.Push();

t = a-›get();

a.PopOne();

t = a-›get();

a.Rollback();

t = a-›get();

return 0;

}

Шаг 24 - Как создавать ТОЛЬКО локальные переменные.

В Шаге 17 мы изыскали способ подавить создание локальных переменных. Решим обратную задачу - как подавить иные способы их создания. А какие иные? Любые другие способы предполагают вызов оператора operator new()для выделения памяти и потом вызов конструктора. Значит, надо объявить operator new()закрытым членом класса, да и все. Ничего в нем делать не надо, а сразу назад. Попробуем?

class CNoHeap {

public:

int a;

private:

void* operator new(size_t size) { return NULL; }

};

int main () {

/*

CNoHeap* firstTestNoHeap = new CNoHeap; // Не откомпилируется

*/

CNoHeap secondTestNoHeap; // А это пожалуйста.

return 0;

}

Теперь, если определить макрос:

#define DECLARE_LOCAL \

private: \

void* operator new(size_t size) { return NULL; }

и потом вкладывать его во всякие разные объекты, отвечающие за захват и освобождение ресурсов, то получится весьма удобно; Вы ГАРАНТИРОВАННО освободите любые ресурсы, захваченные в конструкторе и освобождаемые в деструкторе, в том числе в исключении. В любом случае, всякое ограничение уменьшает энтропию.

Для Шага 17, где мы рисовали производящие и разрушающие функции, тоже можно нарисовать макрос… и назвать его DECLARE_DYNCREATE. То есть, я хочу сказать, что Вы можете аккуратно переписать нужное из него в свою версию, а в результате получите

class CSomeClass {

DECLARE_NOLOCAL

public:

bool Initialize (param list);

};

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

Шаг 25 - Как сделать виртуальной свободную функцию.

Чаще всего этот прием я видел в отношении оператора operator‹‹. Точнее, не чаще, а всегда. На нем и разберем. Пусть у нас есть иерархия классов, и мы хотим определить диагностическую функцию Dump(). Она должна вываливать диагностику в заданное что-то ( CDestination). У нас есть два варианта: или сделать функцию виртуальной в иерархии классов:

class CBase {

virtual void Dump(CDestination& ds) = 0;

};

class CFirst: public CBase {

void Dump (CDestination& ds);

};

class CSecond: public CBase {

void Dump (CDestination& ds);

};

Или перегружать ее для каждого класса иерархии или в классе, или в свободной функции:

CDestination {

void Dump (CFirst& fs);

void Dump (CSecond& sc);

};

void Dump (CDestination& ds, CThird& td);

void Dump (CDestination& ds, CFourth& fr);

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

Но у второго варианта есть одно преимущество: функцию Dump()можно обозвать оператором operator‹‹, и это будет выглядеть весьма презентабельно:

// Это декларация

CDestination {

CDestination& operator‹‹ (CFirst& fs);

};

CDestination& operator‹‹ (CDestination& ds, CSecond& sc);

// А это применение

dStream ‹‹ dObject;

Как сделать так, чтобы сохранить замечательное полиморфное поведение первого варианта, и применить эту радость идиота operator‹‹? Легко: пусть operator‹‹вместо реальной работы просто вызывает виртуальную Dump(). Именно так сделано в MFC- объект afxDumpвызывает виртуальную Dump()именно через operator‹‹. (Можно что угодно говорить про Microsoft, но факт есть факт - огромное число полезных и интересных приемов использовано в их продуктах и "… взять их у нее - наша задача!").

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

Интервал:

Закладка:

Сделать


Albert Makhmutov читать все книги автора по порядку

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




Идиомы и стили С++ отзывы


Отзывы читателей о книге Идиомы и стили С++, автор: Albert Makhmutov. Читайте комментарии и мнения людей о произведении.


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

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