Статический и динамический полиморфизм в c++, Дмитрий...

34
1

Upload: yandex

Post on 11-Nov-2014

300 views

Category:

Technology


4 download

DESCRIPTION

На примере некоторых архитектурных решений Крипты Дмитрий расскажет о способах реализации полиморфного поведения в программах на C++, о преимуществах и недостатках этих способов, а также о новых возможностях C++11.

TRANSCRIPT

Page 1: Статический и динамический полиморфизм в C++, Дмитрий Леванов

1

Page 2: Статический и динамический полиморфизм в C++, Дмитрий Леванов

2

Статический и динамический полиморфизм в C++

Дмитрий ЛевановВедущий разработчик Крипта

Page 3: Статический и динамический полиморфизм в C++, Дмитрий Леванов

3

Крипта

Отвечает на вопрос «Кто?»Определяет интересы по поведению в

интернетеИспользуется для таргетинга рекламыОт др.-греч. κρυπτή — крытый подземный

ход, тайник

Page 4: Статический и динамический полиморфизм в C++, Дмитрий Леванов

4

Как учили Крипту

Матрикснет

Обучение Контроль

Логи+

Page 5: Статический и динамический полиморфизм в C++, Дмитрий Леванов

5

Крипта

Page 6: Статический и динамический полиморфизм в C++, Дмитрий Леванов

6

Разработка Крипты

Много логов в разных форматахСложные цепочки обработкиВысокие требования к производительности

Много одинаковой похожей логикиХочется делать всё однообразно

Page 7: Статический и динамический полиморфизм в C++, Дмитрий Леванов

7

Модель распределенных вычислений MapReduce

Дмитрий ЛевановВедущий разработчик Крипта

Page 8: Статический и динамический полиморфизм в C++, Дмитрий Леванов

8

Полиморфизм

Способ поставить в соответствие некой грамматической конструкции контекстно-зависимую семантику

или, по-русски:

Текст программы [почти] один и тот же, а смысл разный

Page 9: Статический и динамический полиморфизм в C++, Дмитрий Леванов

9

Виртуальный полиморфизм

class Base {virtual void do() { std::cout << “base”; }

};

class Derived : public Base {virtual void do() { std::cout << “derived”;

}};

Base* b = new Derived();b->do(); // derived

Page 10: Статический и динамический полиморфизм в C++, Дмитрий Леванов

10

Виртуальный полиморфизм: плюсы

ООП-шненькоТипобезопасноРаботают фичи, зависящие от _vptr

Page 11: Статический и динамический полиморфизм в C++, Дмитрий Леванов

11

Виртуальный полиморфизм: минусы

Медленный вызов методовНадо поддерживать иерархию классовГрабли с виртуальными методамиПриходится иметь дело с T* или T&Статический метод не может быть

виртуальнымИнвариантность

Page 12: Статический и динамический полиморфизм в C++, Дмитрий Леванов

12

Зачастую все сводится к…

void f(Handler* h) {h->do();

}

//...

f(new MyHandler());

Page 13: Статический и динамический полиморфизм в C++, Дмитрий Леванов

13

Зачастую все сводится к…

void f(Handler* h) {h->do();

}

//...

f(new MyHandler());

template<typename H>void f(const H& h) {

h.do();}

//...

f(MyHandler());

Page 14: Статический и динамический полиморфизм в C++, Дмитрий Леванов

14

Продолжаем улучшать

void f(Handler* h) {h->do();

}

//...

f(new MyHandler());

template<typename H>void f(const H& h) {

h();}

//...

f(MyHandler());

Page 15: Статический и динамический полиморфизм в C++, Дмитрий Леванов

15

Вообще хорошо!

void f(Handler* h) {h->do();

}

//...

f(new MyHandler());

template<typename H>void f(const H& h) {

h();}

//...

f([]() { /* do */ });

Page 16: Статический и динамический полиморфизм в C++, Дмитрий Леванов

16

Или так

void f(Handler* h) {h->do();

}

//...

f(new MyHandler());

template<typename H>void f() {

H::do();}

//...

f<MyHandler>();

Page 17: Статический и динамический полиморфизм в C++, Дмитрий Леванов

17

Статический полиморфизм: плюсы

ТипобезопасноБыстрый вызов методовНе надо наследоватьсяНе надо иметь дело с указателямиМожно использовать лямбды

Page 18: Статический и динамический полиморфизм в C++, Дмитрий Леванов

18

Статический полиморфизм: минусы

Нельзя положить в коллекциюСложно проверять правильность кодаЕсть ограничения компилятораМедленно компилируетсяМожет распухнуть бинарникНе во всех IDE правильно работает

автокомплит

Page 19: Статический и динамический полиморфизм в C++, Дмитрий Леванов

19

«Виртуальный» вызов без virtuala.k.a. Curiously Recurring Template Pattern

template<typename Derived>class Base { void do() { static_cast<Derived*>(*this)::do(); }};

class MyDerived : public Base<MyDerived> { void do() { std::cout << "my derived"; }};

Base<MyDerived>* b = new MyDerived();b->do(); // my derived

Page 20: Статический и динамический полиморфизм в C++, Дмитрий Леванов

20

Tag dispatchingtemplate <class InputIter, class Dist>void advance (InputIter& it, Dist n);

template <class InputIter, class Dist>void advance(InputIter& i, Dist n) { while (n--) ++i;}

template <class RndAcsIter, class Dist>void advance(RndAcsIter& i, Dist n) { i += n;}

Page 21: Статический и динамический полиморфизм в C++, Дмитрий Леванов

21

Tag dispatchingtemplate <class InputIter, class Dist>void advance (InputIter& it, Dist n);

template <class InputIter, class Dist>void advance(InputIter& i, Dist n, input_iter_tag) { while (n--) ++i;}

template <class RndAcsIter, class Dist>void advance(RndAcsIter& i, Dist n, rnd_acs_iter_tag) { i += n;}

Page 22: Статический и динамический полиморфизм в C++, Дмитрий Леванов

22

Tag dispatchingtemplate <class InputIter, class Dist>void advance (InputIter& it, Dist n) { typename iter_traits<InputIter>::iter_category cat; advance(i, n, cat);}

template <class InputIter, class Dist>void advance(InputIter& i, Dist n, input_iter_tag) { while (n--) ++i;}

template <class RndAcsIter, class Dist>void advance(RndAcsIter& i, Dist n, rnd_acs_iter_tag) { i += n;}

Page 23: Статический и динамический полиморфизм в C++, Дмитрий Леванов

23

ЗадачаНапример, мы пишем дебаггерЕсть множество объектов, не связанных

какой-либо иерархиейХотим сложить их в одну коллекцию,

проитерироваться по ней, и сдампить объекты

int x = 10;Foo bar;objects.add(x);objects.add(bar);

for (const auto& obj : objects) { obj.dump();}

Page 24: Статический и динамический полиморфизм в C++, Дмитрий Леванов

24

External polymorphismclass Dumpable { virtual void dump() const = 0;};

template<typename T>class ConcreteDumpable<T> : public Dumpable { const T& value;public: ConcreteDumpable(const T& value) : value(value) {}

virtual void dump() const { ::dump(value); }};

void dump(const Foo& foo) { foo.printToConsole();}

Page 25: Статический и динамический полиморфизм в C++, Дмитрий Леванов

25

External polymorphismclass Dumper { std::vector<Dumpable*> dumpables;public: template<typename T> void add(T& obj) { auto dumpable = new ConcreteDumpable<T>(obj); dumpables.push_back(dumpable); } void dumpAll() const { for (auto d : dumpables) { d->dump(); } }} dumper;

int x = 10;Foo bar;

dumper.add(x);dumper.add(foo);dumper.dumpAll();

Page 26: Статический и динамический полиморфизм в C++, Дмитрий Леванов

26

External polymorphism

Симбиоз виртуального и статического полиморфизма

Для поддержки нового типа T надо добавить только ::dump(T)

Можно строить параллельные иерархии

Page 27: Статический и динамический полиморфизм в C++, Дмитрий Леванов

27

Новые возможности C++11: лямбдыint x = 10;vector<int> v = { 1, 2, 3 };

for_each(v.begin(), v.end(), [x](int i){cout << i+x;});

class Lambda { int x;public: Lambda(int x) : x(x) {} void operator( )(int i) {cout << i+x;}};

for_each(Lambda());

Page 28: Статический и динамический полиморфизм в C++, Дмитрий Леванов

28

Новые возможности C++14: лямбдыint x = 10;vector<int> v = { 1, 2, 3 };

for_each(v.begin(), v.end(), [x](auto i){cout << i+x;});

class Lambda { int x;public: Lambda(int x) : x(x) {}

template<typename T> void operator( )(T i) {cout << i+x;}};

Page 29: Статический и динамический полиморфизм в C++, Дмитрий Леванов

29

Новые возможности C++11: std::function

using namespace std;

void print(int i) { cout << i; }

struct Print { void operator()(int i) {cout << i+x;}}

function<void(int)> p1 = print;function<void(int)> p1 = Print;function<void(int)> p1 = [](int i) {cout << i+x;};

Page 30: Статический и динамический полиморфизм в C++, Дмитрий Леванов

30

Новые возможности C++11: std::function

using namespace std;

void print(int i) { cout << i; }

struct Print { void operator()(int i) {cout << i+x;}}

function<void(int)> p1 = print;function<void(int)> p1 = Print;function<void(int)> p1 = [](int i) {cout << i+x;};

Page 31: Статический и динамический полиморфизм в C++, Дмитрий Леванов

31

Новые возможности C++11: std::function

Медленные (virtual под капотом)Обеспечивают поддержку концептовПозволяют сохранить исполняемые объекты

Не замена шаблонам и виртуальным методам!

Page 32: Статический и динамический полиморфизм в C++, Дмитрий Леванов

32

Топ фич (субъективный)

1. Обычный метод/функция2. Шаблонный метод/функция (+лямбды)3. Шаблонный класс (+CRTP)4. Виртуальный метод5. Внешний полиморфизм6. std::function

Page 33: Статический и динамический полиморфизм в C++, Дмитрий Леванов

33

Спасибо за внимание!

Дмитрий ЛевановВедущий разработчик Крипта

[email protected]