Еще раз про экзамен

56
Еще раз про экзамен 22 мая – 10:00 Сбор у баобаба. Для тех, кто придет позже – будет объявление на расписании 3 курса Вопрос 33 (RTTI и typeid) вычеркивается Еще одна возможность сдать спец.курс будет в официальный день сдачи, 6 июня, в 10:00, сбор у баобаба

description

Еще раз про экзамен. 22 мая – 10 :00 Сбор у баобаба. Для тех, кто придет позже – будет объявление на расписании 3 курса Вопрос 33 ( RTTI и typeid) вычеркивается Еще одна возможность сдать спец.курс будет в официальный день сдачи, 6 июня, в 10:00, сбор у баобаба. Задачи на 12 мая. - PowerPoint PPT Presentation

Transcript of Еще раз про экзамен

Page 1: Еще раз про экзамен

Еще раз про экзамен 22 мая – 10:00

Сбор у баобаба. Для тех, кто придет позже – будет объявление на расписании 3 курса

Вопрос 33 (RTTI и typeid) вычеркивается

Еще одна возможность сдать спец.курс будет в официальный день сдачи, 6 июня, в 10:00, сбор у баобаба

Page 2: Еще раз про экзамен

Задачи на 12 мая

Язык С++ - 2

Page 3: Еще раз про экзамен

Задача: из каких int состоит double? Вариант с union

union {double x;int a[2];

};

x = 2.71828;cout << a[0] << " " << a[1];

Вариант с преобразованием указателя

x = 2.71828;

int* p = (int*)&x;

cout << a[0] << " " << a[1];

Или лучше так:

int* p =reinterpret_cast<int*>(&x);

(см. ниже)

Page 4: Еще раз про экзамен

Задачи на 19 мая

Язык С++ - 4

Page 5: Еще раз про экзамен

ASSERT#ifdef DEBUG

#define ASSERT(cond) \ if (!(cond)) \

cout << "Условие " #cond "не выполняется";#else

#define ASSERT(cond)#endif

Page 6: Еще раз про экзамен

Cписок ошибок#define ERROR_TABLE map<int, string> errors;#define ERROR(num, message) errors[num] = message;

…ERROR_TABLEERROR(1, “Какая-то проблема“)ERROR(2, “Все плохо..“)ERROR(3, “У вас все неправильно“)

Page 7: Еще раз про экзамен

Еще про задачу о списке ошибокУсложним немного задачу:

Пусть я составил список ошибок, которые у меня будут выдаваться – с номерами и текстом ошибок. Но номера я записываю не как числа, а как символьные имена. И я бы хотел, чтобы с этими именами автоматически связывались числа 1, 2… по порядку.

Т.е. я хочу, чтобы я записал список ошибок в каком-то таком виде:

ERROR(someError, “Какая-то проблема“)ERROR(allBad, “Все плохо..“)ERROR(allWrong, “Все неправильно“)

И автоматически генерировалось что-то такое:

еnum {someError,allBad,allWrong,

};

map<int, string> errors;errors[someError] =

“Какая-то проблема“;errors[allBad] =

“Все плохо..“)errors[allWrong] =

“Все неправильно“;

Как это сделать?

Это будет еще одно домашнее задание, самое последнее, просто для тех, кому это будет интересно..

Page 8: Еще раз про экзамен

Прием: разные определения для одного и того же макроса Подсказка 1 – возможная схема

--- errlist.h --------------------------------ERROR(someError, “Какая-то проблема“)ERROR(allBad, “Все плохо..“)ERROR(allWrong, “Все неправильно“)

-- основная программа ----------------- … … определения, чтобы сгенерировать enum #include "errlist.h"

… определения, чтобы сгенерировать map #include "errlist.h"

Подсказка 2 – вам может потребоваться оператор препроцессора #undef #undef ABC Смысл: отменить определение ABC – нужно, если мы хотим его переопределить

Page 9: Еще раз про экзамен

Задача: Сколько квадратов?// Иерархия классов

class CShape {public:

virtual ~CShape() {}// Еще методы…

};

class CSquare : public CShape {// Методы…

};

class CCircle : public CShape { // Методы…

};

class CRhomb : public CShape { // Методы…

};

// Пример создания масива

vector<CShape*> v;v.push_back(new CCircle());v.push_back(new CSquare());v.push_back(new CRhomb());…

// Считаем количество квадратов

int cnt = 0;

for (vector<CShape*>::iterator p = v.begin(); p != v.end(); p++) {if (typeid(**p) == typeid(CSquare)) cnt++;

}

Page 10: Еще раз про экзамен

Замечание про RTTI

Page 11: Еще раз про экзамен

Почему плохо использовать RTTI? Когда это все-таки имеет смысл? Хочется использовать

typeid? Скорее всего, надо ввести виртуальную функцию.(smell…)

if (typeid(*p) == typeid(CCircle) cout << "Это круг";

else if (typeid(*p) == typeid(CSquare)cout << "Это квадрат";

else if (typeid(*p) == typeid(CTriang)cout << "Это треугольник";

cout << "Это " << p->name();

Когда все-таки имеет смысл использовать?

Если мы не можем добавить виртуальную функцию в базовый класс. (Например, классы, производные от CView)

Page 12: Еще раз про экзамен

Сортировка по последним n цифрам (с помощью функтора)class my_comparator {

int m; // 10^npublic:

my_comparator(int n){

// Calculate 10^nm = 1;for (int i = 0; i < n; i+

+) m *= 10;

}

bool operator() (int i, int j){

return i % m < j % m;}

};

my_comparator cmp(n);sort(v.begin(), v.end(), cmp);

или

sort(v.begin(), v.end(), my_comparator(n));

Page 13: Еще раз про экзамен

Снова сумма положительных элементов Так мы написали..

template <class T>typename T::value_type sumpos(T b, T e){ typename T::value_type sum;

for (T p = b; p!=e; p++) { if (*p > 0) { sum += *p; } } return sum;}

Просьба заказчика – пусть тип результата всегда int или double

T.e. требуется по одному типу найти другой по правилу: float, double double Все остальное int

Легко сказать – как это реализовать?

trait !

Язык С++ 13

Page 14: Еще раз про экзамен

Cумма положительных элементов – новое решениеtemplate <class T>struct sum_trait {

typedef int sum_type;};

template <>struct sum_trait<float> {

typedef double sum_type;};

template <>struct sum_trait<double> {

typedef double sum_type;};

#define SUM_TYPE \ typename sum_trait \ <typename T::value_type>:: \

sum_type

template <class T>SUM_TYPE sumpos(T b, T e){

SUM_TYPE sum = 0;

… дальше без изменений …

}

Язык С++ 14

Page 15: Еще раз про экзамен

casts(static_cast,

dynamic_cast и т.д.)

Page 16: Еще раз про экзамен

Оказывается, преобразования бывают 4 видов

Вместо существующего оператора преобразования рекомендуется выбрать один из 3 способов.

1. static_cast

Мы создаем объект, устроенный внутри по другому, но с тем же смыслом (примерно…)

Т.е. “другие биты, тот же смысл…”

T.e. раньше писали:

int i = (int)x;complex x = (complex)x;

Теперь рекомендуется писать:

int i = static_cast<int>(x);

2. reinterpret_cast double* px = &x;char* p = (char*) px;

Те же биты, другой смысл…Объект тот же, но мы его интерпретируем по другому.

Только в 3 случаях: указатель указатель указатель целое целое указатель

Т.е. рекомендуется писать:char* p =

reinterpret_cast<char*>(px);

Page 17: Еще раз про экзамен

const_cast3. const_cast

Пусть у нас есть const int* p;

Но мы точно знаем, что это не константа (просто неправильно описан параметр и т.д.). И очень надо ее поменять.

int* p1 = (int*)p;*p = 55;

Т.е. смысл тот же, биты те же. Только задаем или убираем спецификации const

Т.е. рекомендуется писать:

int* p1 = const_cast<int*>(p);

Page 18: Еще раз про экзамен

dynamic_castshape* p;

Пусть мы точно знаем, что p указывает на square

square* p1 = (square*)p;p1->… делаем что-то

специальное для квадрата

(Это называется downcasting)

Вообще-то можно проверить, действительно ли это квадрат.. По таблице вирт.функций Только если есть хотя бы

одна вирт. функция Должна быть включена

опция “Enable Runtime Type Info”

Можно написать так:square* p1 =

dynamic_cast<square*>(p);if (p1 == 0)

cout << "Ошибка!";

Page 19: Еще раз про экзамен

dynamic_cast - продолжениеТоже для ссылок:

shape& sh;square& p1 =

dynamic_cast<square&>(sh);

Если не то – исключение(bad_cast)

Заключение: Все виды cast лучше

применять пореже Но, если вы действительно

понимаете, зачем это вам надо – ОК, ничего страшного.

Page 20: Еще раз про экзамен

Namespace

Язык С++ 20

Page 21: Еще раз про экзамен

Зачем нужны namespace?Проблема:Пусть есть две библиотеки

классов:

Библиотека ABCLIB.класс stack …

Библиотека KLMLIB.класс stack

#include <abclib.h>#include <klmlib.h>

stack st; // Ошибка!

Решение: В библиотеке ABCLIB:namespace abc {

…class stack { ……

} То же в KLMLIB:namespace klm {

… class stack …

}

Теперь abc::stack и klm::stackЯзык С++ 21

Page 22: Еще раз про экзамен

Как обращаться к именам из namespace? Полное имя:

abc::stackklm::stack

using объявлениеusing abc::stack;

stack abc::stack

using директиваusing namespace abc;

stack пытается найти в abc

Замечания:

и using объявление и using директива действуют до конца блока.

Совет: в h файлах – только полное имя

Язык С++ 22

Page 23: Еще раз про экзамен

Еще возможности Инкрементальное

определение

namespace abc { … определения …}

… что-то вне namespace …

namespace abc { … еще определения …}

Глобальное пространство имен::f() – глобальная функция

using ::f;

M.б. вложенныеabc::klm

Язык С++ 23

Page 24: Еще раз про экзамен

Еще возможности - 2 Безымянные (анонимные)

namespace

namespace { int v; …} Генерируется уникальное имя + using директива

namespace <уник.имя> { int v; …}using namespace <уник.имя>;

Означает: Переменную v можно использовать только от того места, где она определена, и до конца файла

- примерно то же, что static

Язык С++ 24

Page 25: Еще раз про экзамен

Что мы не прошли…

Язык С++ - 25

Page 26: Еще раз про экзамен

Множественное наследование

Язык С++ - 26

Page 27: Еще раз про экзамен

Множественное наследование - 1class Car {// Автомобиль

…};

class Ship { // Корабль…

};

class Amphibia : public Car, public Ship {…

};

В реальности с множественным наследованием обычно получается довольно сложно…

Page 28: Еще раз про экзамен

Множественное наследование - 2Надо ли использовать?

Pазные точки зрения… Да

Например, ATL Нет

Например, MFC Да, но только для интерфейсов

(абстрактныe классов, вообще без кода, только с чисто виртуальными функциями) (Так в Java, например)

Page 29: Еще раз про экзамен

Diamond problem (ромбовидная диаграмма) А / \B1 B2 – наследники A \ / C – наследник B1, B2

diamond problem ромбовидная диаграмма

Проблема:class A {protected:

int x;void f();

};

Сколько в классе C экземпляров поля x? Хорошо бы один…

(например, поле "руль" или "мотор" для амфибии)

Vehicle (средство передвижения) поля "руль", "мотор"

/ \ Car Ship \ / Amphibia

Page 30: Еще раз про экзамен

Виртуальные базовые классыclass A { … }

class B1 : public virtual A { …

};

class B2 : public virtual A { …

};

class C : public B1, public B2 {…

};

Теперь x будет в C один раз Класс А называется "виртуальный базовый класс"

Page 31: Еще раз про экзамен

private и protected наследование

Язык С++ - 31

Page 32: Еще раз про экзамен

Пример Класс group - студенческая

группа.Представляется, как вектор из объектов класса student

class group {vector<student> vect;

public:void add(const student& s)void print() const;…

};

void group::add(const student& s){

vect.push_back(st);}

void group:: print() const{

…for (p = vect.begin(); p != vecn.end(); p++)

…}

Page 33: Еще раз про экзамен

То же с private наследованием Можно написать короче

class group : vector<student> {public:

void add(const student& s)void print() const;…

};

void group::add(const student& s){

push_back(st);}

void group:: print() const{

…for (p = begin(); p != end();

…}

Public наследование было бы неправильно!

private неследование – унаследованные меиоды становятся private Т.е. снаружи

наследование не видно…

Page 34: Еще раз про экзамен

protected наследование Примерно аналогично Встречается еще реже

Page 35: Еще раз про экзамен

Разные полезные вещи

Язык С++ - 35

Page 36: Еще раз про экзамен

Преобразования строка число atoi, itoa, atof, _fcvt и т.д.

строковые потоки

ostringstream sout;sout << i << " " << x;string s = sout.str();

И аналогично istringstream.

Форматный ввод/вывод в т.ч. в строку.

char s[20];sprinf(s, "%10.3lf", x);

Форматный вывод в MFC

CString s;s.Format("%10.3lf", x);

Page 37: Еще раз про экзамен

Функции с переменным числом аргументов #include <stdarg.h>

va_start, va_arg, va_end

int mysum(int n, …)

Вызов:cout << mysum(2, n, k);cout << mysum(4, i, j, k, l);

Не рекомендуется использовать:Нет проверки параметров компилятором: mysum(2, i, j, k) mysum(2, 3.14, "abc")

Но иногда удобно

Page 38: Еще раз про экзамен

Побитовые операции для целых чисел & - побитовое "И"

| - побитовое "ИЛИ"

^ - побитовое «исключающее ИЛИ»

~ - инвертировать виты

<< - сдвиг влево

<< - сдвиг влево

Page 39: Еще раз про экзамен

Еще возможности для работы с битами Битовые поля

class { int a:3; int b:4; int c:1;};

vector<bool>

bitset<n>

bitset<100> b;b[i] = true;if ( b[i] ) …

Page 40: Еще раз про экзамен

Полезные вещи в стандартной

библиотеке и в boost

Язык С++ - 40

Page 41: Еще раз про экзамен

shared_ptr Указатели со счетчиком ссылок

#include <memory>using namespace std::tr1;

{ shared_ptr<int> p(new int(56)); … {

shared_ptr<int> p1 = p;… // Два указателя на 56

} // Теперь только один …} // Теперь нет

указателей// Память

освобождается

Page 42: Еще раз про экзамен

shared_ptr Если не хотите думать о том,

когда освобождать память

class abc {shared_ptr<int> p;

public:abc() : p(new int(56)){}

// В деструкторе писать// ничего не надо

};

Для управления разделяемыми объектами

Page 43: Еще раз про экзамен

Алгоритмы, параметры у которых - функции (или функторы) find_if

bool isPos(int i){ return i > 0;}

find_if(v.begin(), v.end(), isPos);

Много такого типа remove_if transform for_each … и т.д.

Лично я почти никогда не использую…

Page 44: Еще раз про экзамен

Итераторы вставки, итераторы потоковcopy(v.begin(), v.end(), v1.begin());

С помощью copy можно дописать в конецcopy(v.begin(), v.end(), back_inserter(v1));

С помощью copy можно записать в файл

#include <iterator>…ostream_iterator<int> out_it(cout, “ “);copy(v.begin(), v.end(), out_it);

Page 45: Еще раз про экзамен

Еще в boost boost:: hash_map, hash_set

В C++ 0x – unordered_map, unordered_set

Вообще очень много чего (regex, graphs)

Page 46: Еще раз про экзамен

C++0x

Язык С++ - 46

Page 47: Еще раз про экзамен

C++ 0x – новый стандарт языкаТолько некоторые из новых

возможностей:

Инициализация контейнеров списком инициализации:

vector<int> v = {3, 7, 11 };

Цикл по контейнеру:

vector<int> v;for (x: v) { …

Вывод типа (type inference)

auto i = 3;auto x = 3.14;auto n = abc(x, y);

for (auto p = v.begin(); p != v.end(); p++)

Page 48: Еще раз про экзамен

lambdas Функция, параметр которой –

функция Пишем в параметре прямо

код функции

find_if(v.begin(), v.end(),[] (int x) { return x > 0; } );

sort(v.begin(), b.end(), [] (int x, int y) { return x % 10 < y % 10; } );

void f(vector<int> v, int n){

int m = 1;for (int i = 0; i < n; i++) m *= 10;

sort(v.begin(), b.end(), [] (int x, int y) { return x % m < y % m; } );

}

Page 49: Еще раз про экзамен

Conceptstemplate <class T>T max(T x, T y){

return y < x ? x : y;} template <Comparable T>T max(T x, T y){

return y < x ? x : y;}

concept Comparable<typename T> {bool operator<(T x, T y);

};

Более понятные сообщения об ошибках:

complex c1, c2;max(c1, c2);"Error: complex is not

Comparable"

Обнаружение ошибок еще в шаблоне:

template <Comparable T>T max(T x, T y) {

… max = x; …"operator = not in Comparable"

Page 50: Еще раз про экзамен

А вот что я сказал бы, если бы еще

было время…

Язык С++ - 50

Page 51: Еще раз про экзамен

main, cin, cout, cerrint main(int argc, char* argv[])

argc – количество параметров командной строки

argv – параметры

myprog aaa bbb ccc

argc = 4argv[0] = "myprog";argv[1] = "aaa";argv[2] = "bbb";argv[3] = "ccc";

cin, cout переназначаются !

myprog >abc.txtcout пишет в abc.txt

myprog <klm.txtcin читает из klm.txt

myprog >>abc.txtcout дописывает в конец abc.txt

cerr – не переназначается с помощью > (для сообщений об ошибках, например.

Page 52: Еще раз про экзамен

разное о new/delete, void* nothrow

int* p = new (nothrow) int [1000];

Не выбрасывать исключение (вернуть 0)

void* - указатель неизвестно на чтоОбязательно надо потом преобразовывать

placement new

char s[10000];abc* p = new ((void*)s) abc;

Явный вызов деструктора

p->~abc();

Page 53: Еще раз про экзамен

pointers to members Pointers to members

class abc { int a; int b; int c; int d; …};

int abc::* p; // Какое-то // целое поле в abc

p = abc::d;abc x;x.*p = 56;

Чаще применяется для методов:

class abc { void draw(); void print(); void clear(); void save();

…};

myfunc(abc::print);

Page 54: Еще раз про экзамен

extern "C" extern "C"

--- abc.h ------------------------------extern "C" void f(int i);

// Определено в C файле (не в C++)----------------------------------------

Page 55: Еще раз про экзамен

Разные замечания Наследование и перегрузка

методов

class B {public:

void f(int i);};

class D : public B {public:

void f(const char* s);

};D x;x.f(5); // Ошибка

Виртуальные функции в конструкторе и деструкторе

Переопределение оператора ++.x++ и ++x ??operator++(); // ++xoperator++(int); // x++

Page 56: Еще раз про экзамен

И это все…И главное, что не успел

сказать – лично мне было очень интересно, может быть

и вам тоже!

Язык С++ - 56