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

Post on 11-Nov-2014

296 Views

Category:

Technology

4 Downloads

Preview:

Click to see full reader

DESCRIPTION

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

TRANSCRIPT

1

2

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

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

3

Крипта

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

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

ход, тайник

4

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

Матрикснет

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

Логи+

5

Крипта

6

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

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

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

7

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

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

8

Полиморфизм

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

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

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

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

10

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

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

11

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

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

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

12

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

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

}

//...

f(new MyHandler());

13

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

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

}

//...

f(new MyHandler());

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

h.do();}

//...

f(MyHandler());

14

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

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

}

//...

f(new MyHandler());

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

h();}

//...

f(MyHandler());

15

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

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

}

//...

f(new MyHandler());

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

h();}

//...

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

16

Или так

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

}

//...

f(new MyHandler());

template<typename H>void f() {

H::do();}

//...

f<MyHandler>();

17

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

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

18

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

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

автокомплит

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

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;}

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;}

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;}

23

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

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

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

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

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

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();}

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();

26

External polymorphism

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

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

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

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());

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;}};

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;};

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;};

31

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

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

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

32

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

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

33

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

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

levanov@yandex-team.ru

top related