---------------
void my_event_handler(BBwindow* pw)
{
    if (auto pb = dynamic_cast<Ival_box*>(pw)) { // czy pw wskazuje obiekt typu Ival_box?
        //...
        int x = pb->get_value();  // uycie Ival_box
        //...
    }
    else {
        //... ups! obsuga niespodziewanego zdarzenia...
    }
}
---------------
dynamic_cast<T*>(p)
---------------
class BB_ival_slider : public Ival_slider, protected BBslider {
    //...
};

void f(BB_ival_slider* p)
{
    Ival_slider* pi1 = p;                             // OK
    Ival_slider* pi2 = dynamic_cast<Ival_slider*>(p); // OK

    BBslider* pbb1 = p;                               // bd: BBslider jest baz chronion
    BBslider* pbb2 = dynamic_cast<BBslider*>(p);      // OK: pbb2 staje si nullptr
}
---------------
class My_slider: public Ival_slider { // polimorficzna baza (Ival_slider ma funkcje wirtualne)
    //...
};

class My_date : public Date {         // baza niepolimorficzna (Date nie ma funkcji wirtualnych)
    //...
};

void g(Ival_box* pb, Date* pd)
{
    My_slider* pd1 = dynamic_cast<My_slider*>(pb); // OK (Ival_slider jest rodzajem Ival_box)
    My_date* pd2 = dynamic_cast<My_date*>(pd);     // bd: klasa Date nie jest polimorficzna
}
---------------
class Io_obj { // klasa bazowa obiektowego systemu wejcia-wyjcia
    virtual Io_obj* clone() = 0;
};

class Io_date : public Date, public Io_obj { };

void f(Io_obj* pio)
{
    Date* pd = dynamic_cast<Date*>(pio);
    //...
}
---------------
void g(Ival_box* pb, Date* pd)
{
    void* pb2 = dynamic_cast<void*>(pb); // OK
    void* pd2 = dynamic_cast<void*>(pd); // bd: klasa Date nie jest polimorficzna
}
---------------
void fp(Ival_box *p)
{
    if (Ival_slider* is = dynamic_cast<Ival_slider*>(p)) { // czy p wskazuje obiekt klasy Ival_slider?
        //... uycie is...
    }
    else {
        //... *p nie jest suwakiem; inne moliwoci...
    }
}
---------------
void fr(Ival_box& r)
{
    Ival_slider& is = dynamic_cast<Ival_slider&>(r);  // r odnosi si do obiektu klasy Ival_slider!
    //... uycie is...
}
---------------
void g(BB_ival_slider& slider, BB_ival_dial& dial)
{
    try{
        fp(&slider); // wskanik do BB_ival_slider przekazany jako Ival_box*
        fr(slider);  // referencja do BB_ival_slider przekazana jako Ival_box&
        fp(&dial);   // wskanik do BB_ival_dial przekazany jako Ival_box*
        fr(dial);    // pokrto przekazane jako Ival_box
    }
    catch (bad_cast) { // 30.4.1.1
        //...
    }
}
---------------
class Component
    : public virtual Storable { /*...*/};
class Receiver
    : public Component { /*...*/};
class Transmitter
    : public Component { /*...*/};
class Radio
    : public Receiver, public Transmitter { /*...*/};
---------------
void h1(Radio& r)
{
    Storable* ps = &r; // obiekt klasy Radio ma unikatowy obiekt klasy Storable
    //...
    Component* pc = dynamic_cast<Component*>(ps); // pc = 0; Radio ma dwa obiekty klasy Component
    //...
}
---------------
void h2(Storable* ps) // ps moe, ale nie musi wskazywa obiektu klasy Component
{
    if (Component* pc = dynamic_cast<Component*>(ps)) {
        // mamy obiekt klasy Component!
    }
    else {
        // to nie by obiekt klasy Component
    }
}
---------------
void g(Radio& r)
{
    Receiver* prec = &r;                   // Receiver jest zwyk baz klasy Radio
    Radio* pr = static_cast<Radio*>(prec); // OK, niekontrolowane
    pr = dynamic_cast<Radio*>(prec);       // OK, kontrolowane w czasie wykonywania

    Storable* ps = &r;                     // Storable jest wirtualn baz klasy Radio
    pr = static_cast<Radio*>(ps);          // bd: nie mona rzutowa z wirtualnej bazy
    pr = dynamic_cast<Radio*>(ps);         // OK, kontrolowane w czasie wykonywania
}
---------------
Radio* f1(void* p)
{
    Storable* ps = static_cast<Storable*>(p); // zaufaj programicie
    return dynamic_cast<Radio*>(ps);
}
---------------
class Users : private set<Person> { /*...*/};

void f2(Users* pu, const Receiver* pcr)
{
    static_cast<set<Person>*>(pu);            // bd: naruszenie praw dostpu
    dynamic_cast<set<Person>*>(pu);           // bd: naruszenie praw dostpu

    static_cast<Receiver*>(pcr);              // bd: nie mona rzutowaniem pozby si const
    dynamic_cast<Receiver*>(pcr);             // bd: nie mona rzutowaniem pozby si const

    Receiver*pr = const_cast<Receiver*>(pcr); // OK
    //...
}
---------------
void user()
{
    //... otwarcie pliku z ksztatami i doczenie ss jako istream dla tego pliku...

    unique_ptr<Io_obj> p {get_obj(ss)}; // wczytuje obiekt ze strumienia

    if (auto sp = dynamic_cast<Shape*>(p.get())) {
        sp->draw(); // uycie klasy Shape
        //...
    }
    else {
        // ups: "nieksztat" w pliku ksztatw
    }
}
---------------
class Io_obj {
public:
    virtual Io_obj* clone() const =0; // polimorficzna
    virtual ~Io_obj() {}
};
---------------
using Pf = Io_obj*(istream&);   // wskanik do funkcji zwracajcej Io_obj*

map<string,Pf> io_map;          // wie acuchy z funkcjami do tworzenia obiektw

string get_word(istream& is);   // wczytuje sowo z is; zgasza Read_error, jeli odczyt si nie uda

Io_obj* get_obj(istream& is)
{
    string str = get_word(is);  // odczytuje pierwsze sowo
    if (auto f = io_map[str])   // szuka str, aby dosta funkcj
        return f(is);           // wywouje funkcj
    throw Unknown_class{};      // nic nie pasuje do str
}
---------------
class Shape : public Io_obj {
    //...
};
---------------
struct Io_circle : Circle, Io_obj {
    Io_circle(istream&);                                    // inicjacja ze strumienia wejciowego
    Io_circle* clone() const { return new Io_circle{*this}; } // uycie konstruktora kopiujcego
    static Io_obj* new_circle(istream& is) { return new Io_circle{is}; } // dla io_map
};
---------------
io_map["Io_circle"]=&Io_circle::new_circle; // gdzie
---------------
class Io_triangle : public Triangle , public Io_obj {
    //...
};

io_map["Io_triangle"]=&Io_triangle::new_triangle; // gdzie
---------------
template<typename T>
struct Io : T, Io_obj {
public:
    Io(istream&);                                         // inicjacja ze strumienia wejciowego
    Io* clone() const override { return new Io{*this}; }
    static Io* new_io(istream& is) { return new Io{is}; } // dla io_map
};
---------------
using Io_circle = Io<Circle>;
---------------
void f(io<Shape>& ios)
{
    Shape* ps = &ios;
    //...
}
---------------
using Io_date = Io<Date>; // opakowuje konkretny typ
using Io_int = Io<int>;   // bd: nie mona wyprowadza z typu wbudowanego
---------------
template<typename T>
struct Io :Io_obj {
    T val;

    Io(istream&);                                         // inicjacja ze strumienia wejciowego
    Io* clone() const override { return new Io{*this}; }
    static Io* new_io(istream& is) { return new Io{is}; } // dla io_map
};
---------------
using Io_int = Io<int>; // opakowuje typ wbudowany
---------------
template<typename T>
T* get_val<T>(Io_obj* p)
{
    if (auto pp = dynamic_cast<Io<T>*>(p))
        return &pp->val;
    return nullptr;
}
---------------
void user()
{
    //... otwarcie pliku z ksztatami i doczenie ss jako istream dla tego pliku...

    unique_ptr<Io_obj> p {get_obj(ss)}; // wczytuje obiekt ze strumienia

    if (auto sp = get_val<Shape>(p.get())) {
        sp->draw(); // uycie klasy Shape
        //...
    }
    else {
        // ups: "nieksztat" w pliku ksztatw
    }
}
---------------
class Face : public Shape {
public:
    Shape* outline;
    array<Shape*> eyes;
    Shape* mouth;
    //...
};
---------------
void do_someting(Shape& s1, Shape& s2)
{
    if (s1.intersect(s2)) {
        // te dwa ksztaty nakadaj si
    }
    //...
}
---------------
class Circle;
class Triangle;

class Shape {
public:
    virtual bool intersect(const Shape&) const =0;
    virtual bool intersect(const Circle&) const =0;
    virtual bool intersect(const Triangle&) const =0;
};
---------------
class Circle : public Shape {
public:
    bool intersect(const Shape&) const override;
    virtual bool intersect(const Circle&) const override;
    virtual bool intersect(const Triangle&) const override
};

class Triangle : public Shape {
public:
    bool intersect(const Shape&) const override;
    virtual bool intersect(const Circle&) const override;
    virtual bool intersect(const Triangle&) const override;
};
---------------
bool Circle::intersect(const Shape& s) const { return s.intersect(*this); }
bool Circle::intersect(const Circle&) const { cout <<"intersect(circle,circle)\n"; 
(return true; }
bool Circle::intersect(const Triangle&) const { cout <<"intersect(circle,triangle)\n"; 
(return true; }

bool Triangle::intersect(const Shape& s) const { return s.intersect(*this); }
bool Triangle::intersect(const Circle&) const { cout <<"intersect(triangle ,circle)\n"; 
(return true; }
bool Triangle::intersect(const Triangle&) const { cout <<"intersect(triangle ,triangle)\n"; 
(return true; }
---------------
void test(Triangle& t, Circle& c)
{
    vector<pair<Shape*,Shape*>> vs { {&t,&t}, {&t,&c}, {&c,&t}, {&c,&c} };
    for (auto p : vs)
        p.first->intersect(*p.second);
}
---------------
intersect(triangle ,triangle)
intersect(triangle ,circle)
intersect(circle,triangle)
intersect(circle,circle)
---------------
class Shape {
public:
    virtual Rectangle box() const = 0; // prostokt otaczajcy ksztat
    //...
};

class Circle : public Shape {
public:
    Rectangle box() const override;
    //...
};

class Triangle : public Shape {
public:
    Rectangle box() const override;
    //...
};

bool intersect(const Rectangle&, const Rectangle&); // atwe do obliczenia
bool intersect(const Shape& s1, const Shape& s2)
{
    return intersect(s1.box(),s2.box());
}
---------------
bool intersect(const Shape& s1, const Shape& s2)
{
    auto i = index(type_id(s1),type_id(s2));
    return intersect_tbl[i](s1,s2);
}
---------------
class Visitor;

class Node {
public:
    virtual void accept(Visitor&) = 0;
};

class Expr : public Node {
public:
    void accept(Visitor&) override;
};

class Stmt : public Node {
public:
    void accept(Visitor&) override;
};
---------------
void Expr::accept(Visitor& v) { v.accept(*this); }
void Stmt::accept(Visitor& v) { v.accept(*this); }
---------------
class Visitor {
public:
    virtual void accept(Expr&) = 0;
    virtual void accept(Stmt&) = 0;
};
---------------
struct Do1_visitor : public Visitor {
    void accept(Expr&) override { cout << "do1 do Expr\n"; }
    void accept(Stmt&) override { cout << "do1 do Stmt\n"; }
};

struct Do2_visitor : public Visitor {
    void accept(Expr&) override { cout << "do2 do Expr\n"; }
    void accept(Stmt&) override { cout << "do2 do Stmt\n"; }
};
---------------
void test(Expr& e, Stmt& s)
{
    vector<pair<Node*,Visitor*>> vn {&e,&do1}, {&s,&do1}, {&e,&do2}, {&s,&do2}};
    for (auto p : vn)
        p.first->accept(*p.second);
}
---------------
do1 do Expr
do1 do Stmt
do2 do Expr
do2 do Stmt
---------------
class type_info;
const type_info& typeid(expression);  // pseudodeklaracja
---------------
void f(Shape& r, Shape* p)
{
    typeid(r);  // typ obiektu wskazywanego przez r
    typeid(*p); // typ obiektu wskazywanego przez p
    typeid(p);  // typ wskanika, tzn. Shape* (rzadkie, chyba e przez pomyk)
}
---------------
struct Poly {  // polimorficzna klasa bazowa
    virtual void f();
    //...
};

struct Non_poly { /*...*/}; // brak funkcji wirtualnych

struct D1
    :Poly{/*...*/};
struct D2
    : Non_poly { /*...*/};

void f(Non_poly& npr, Poly& pr)
{
    cout << typeid(npr).name() << '\n'; // drukuje co w rodzaju Non_poly
    cout << typeid(pr).name() << '\n';  // nazwa Poly lub klasy wyprowadzonej z Poly
}

void g()
{
    D1 d1;
    D2 d2;
    f(d2,d1); // drukuje "Non_poly D1"
    f(*static_cast<Poly*>(nullptr),*static_cast<Null_poly*>(nullptr)); // ups!
}
---------------
class type_info {
    // dane
public:
    virtual ~type_info();                              // jest polimorficzna

    bool operator==(const type_info&) const noexcept;  // mona porwnywa
    bool operator!=(const type_info&) const noexcept;

    bool before(const type_info&) const noexcept;      // porzdkowanie
    size_t hash_code() const noexcept;                 // do uytku przez unordered_map itp.
    const char*name() const noexcept;                  // nazwa typu

    type_info(const type_info&) = delete;              // uniemoliwia kopiowanie
    type_info& operator=(const type_info&) = delete;   // uniemoliwia kopiowanie
};
---------------
#include<typeinfo>
void g(Component* p)
{
    cout << typeid(*p).name();
}
---------------
#include <typeinfo>

map<string, Layout> layout_table;

void f(B*p)
{
    Layout& x = layout_table[typeid(*p).name()]; // znajduje ukad na podstawie nazwy *p
    //... uycie x...
}
---------------
unordered_map<type_index,Icon> icon_table;  // 31.4.3.2
void g(B*p)
{
    Icon& i = icon_table[type_index{typeid(*p)}];
    //... uycie i...
}
---------------
// niewaciwy sposb uycia informacji czasu wykonywania:
void rotate(const Shape& r)
{
    if (typeid(r) == typeid(Circle)) {
        // nic nie robi
    }
    else if (typeid(r) == typeid(Triangle)) {
        //... obrci trjkt...
    }
    else if (typeid(r) == typeid(Square)) {
        //... obrci kwadrat...
    }
    //...
}
---------------
// niepoprawne wykorzystanie informacji o typie w czasie wykonywania:

class Object { // polimorficzny
    //...
};

class Container : public Object {
public:
    void put(Object*);
    Object* get();
    //...
};

class Ship : public Object { /*...*/};

Ship* f(Ship* ps, Container* c)
{
    c->put(ps);                             // wstawia obiekt Ship do kontenera
    //...
    Object* p = c->g et();                  // pobiera obiekt z kontenera
    if (Ship* q = dynamic_cast<Ship*>(p)) { // sprawdzanie w czasie wykonywania, czy Object to Ship
        return q;
    }
    else {
        //... jakie inne instrukcje (najczciej obsuga bdw)...
    }
}
---------------
Ship* f(Ship* ps, vector<Ship*>& c)
{
    c.push_back(ps);    // wstawia obiekt Ship do kontenera
    //...
    Ship* p = c.back(); // pobiera obiekt Ship z kontenera
    c.pop_back();
    return p;
}