---------------
struct Employee {
    string first_name , family_name;
    char middle_initial;
    Date hiring_date;
    short department;
    //...
};
---------------
struct Manager {
    Employee emp;          // rekord pracownika, ktrym jest meneder
    list<Employee*> group; // podwadni
    short level;
    //...
};
---------------
struct Manager : public Employee {
    list<Employee*> group;
    short level;
    //...
};
---------------
void f(Manager m1, Employee e1)
{
    list<Employee*> elist {&m1,&e1};
    //...
}
---------------
void g(Manager mm, Employee ee)
{
    Employee* pe = &mm;              // OK: kady meneder jest pracownikiem
    Manager* pm = &ee;               // bd: nie kady pracownik jest menederem

    pm->level = 2;                  // katastrofa: ee nie ma skadowej level

    pm = static_cast<Manager*>(pe); // prymitywne rozwizanie: dziaa, bo pe wskazuje
                                    // obiekt mm klasy Manager

    pm->level = 2;                  // w porzdku: pm wskazuje obiekt mm klasy Manager majcy skadow level
}
---------------
class Employee;                   // sama deklaracja, bez definicji

class Manager : public Employee { // bd: klasa Employee nie jest zdefiniowana
    //...
};
---------------
class Employee {
public:
    void print() const;
    string full_name() const { return first_name + ' ' + middle_initial + ' ' + family_name; }
    //...
private:
    string first_name, family_name;
    char middle_initial;
    //...
};

class Manager : public Employee {
public:
    void print() const;
    //...
};
---------------
void Manager::print() const
{
    cout << "Imi i nazwisko: " << full_name() << '\n';
    //...
}
---------------
void Manager::print() const
{
    cout << " Nazwisko: " << family_name << '\n'; // bd!
    //...
}
---------------
void Manager::print() const
{
    Employee::print(); // drukuje informacje oglnopracownicze
    cout << level;     // drukuje informacje specyficzne dla menedera
    //...
}
---------------
void Manager::print() const
{
    print(); // ups!
    // druk informacji specyficznych dla menedera
}
---------------
class Employee { /*...*/};
class Manager : public Employee { /*...*/};
class Director : public Manager { /*...*/};
---------------
class Temporary {/*...*/};
class Assistant : public Employee { /*...*/};
class Temp : public Temporary, public Assistant { /*...*/};
class Consultant : public Temporary, public Manager { /*...*/};
---------------
struct Employee {
    enum Empl_type { man, empl };
    Empl_type type;

    Employee() : type{empl} { }

    string first_name , family_name;
    char middle_initial;

    Date hiring_date;
    short department;
    //...
};

struct Manager : public Employee {
    Manager() { type = man; }

    list<Employee*> group; // podwadni
    short level;
    //...
};
---------------
void print_employee(const Employee* e)
{
    switch (e->type) {
    case Employee::empl:
        cout << e->family_name << '\t' << e->department << '\n';
        //...
        break;
    case Employee::man:
    {   cout << e->family_name << '\t' << e->department << '\n';
        //...
        const Manager* p = static_cast<const Manager*>(e);
        cout << " poziom " << p->level << '\n';
        //...
        break;
    }
    }
}
---------------
void print_list(const list<Employee*>& elist)
{
    for (auto x : elist)
        print_employee(x);
}
---------------
void print_employee(const Employee* e)
{
    cout << e->family_name << '\t' << e->department << '\n';
    //...
    if (e->type == Employee::man) {
        const Manager* p = static_cast<const Manager*>(e);
        cout << " poziom " << p->level << '\n';
        //...
    }
}
---------------
class Employee {
public:
    Employee(const string& name, int dept);
    virtual void print() const;
    //...
private:
    string first_name , family_name;
    short department;
    //...
};
---------------
void Employee::print() const
{
    cout << family_name << '\t' << department << '\n';
    //...
}
---------------
class Manager : public Employee {
public:
    Manager(const string& name, int dept, int lvl);
    void print() const;
    //...
private:
    list<Employee*> group;
    short level;
    //...
};

void Manager::print() const
{
    Employee::print();
    cout << "\poziom " << level << '\n';
    //...
}
---------------
void print_list(const list<Employee*>& s)
{
    for (auto x : s)
        x->print();
}
---------------
int main()
{
    Employee e {"Kowalski",1234};
    Manager m {"Kwiatkowski",1234,2};
    print_list({&m,&e});
}
Wynik:
Kowalski 1234
    poziom 2
Kwiatkowski 1234
---------------
void Manager::print() const
{
    Employee::print(); // to nie jest wywoanie wirtualne
    cout << "\tpoziom " << level << '\n';
    //...
}
---------------
struct B0 {
    void f(int) const;
    virtual void g(double);
};

struct B1 : B0 { /*...*/};
struct B2 : B1 { /*...*/};
struct B3 : B2 { /*...*/};
struct B4 : B3 { /*...*/};
struct B5 : B4 { /*...*/};

struct D : B5 {
    void f(int) const; // przesania f() z klasy bazowej
    void g(int);       // przesania g() z klasy bazowej
    virtual int h();   // przesania h() z klasy bazowej
};
---------------
struct D : B5 {
    void f(int) const override;  // bd: B0::f() nie jest funkcj wirtualn
    void g(int) override;        // bd: B0::g() przyjmuje argument typu double
    virtual int h() override;    // bd: nie ma funkcji h() do przesonicia
};
---------------
void f(int) const noexcept override; // OK (jeli istnieje odpowiednia funkcja f() do przesonicia)
override void f(int) const noexcept; // bd skadni
void f(int) override const noexcept; // bd skadni
---------------
class Derived : public Base {
    void f() override;      // OK, jeli Base ma wirtualn funkcj f()
    void g() override;      // OK, jeli Base ma wirtualn funkcj g()
};

void Derived::f() override  // bd: sowo kluczowe override poza klas
{
    //...
}

void Derived::g()           // OK
{
    //...
}
---------------
int override = 7;

struct Dx : Base {
    int override;

    int f() override
    {
        return override + ::override;
    }
};
---------------
struct Node { // klasa interfejsowa
    virtual Type type() = 0;
    //...
};

class If_statement : public Node {
public:
    Type type() override final; // uniemoliwienie dalszego przesaniania
    //...
};
---------------
class Modified_if_statement : public If_statement {
public:
    Type type() override;  // bd: funkcja If_statement::type() jest finalna
    //...
};
---------------
class For_statement final : public Node {
public:
    Type type() override;
    //...
};

class Modified_for_statement : public For_statement { // bd: klasa For_statement jest finalna
    Type type() override;
    //...
};
---------------
class Derived : public Base {
    void f() final;     // OK, jeli klasa Base zawiera wirtualn funkcj f()
    void g() final;     // OK, jeli klasa Base zawiera wirtualn funkcj g()
    //...
};

void Derived::f() final // bd: specyfikator final poza klas
{
    //...
}

void Derived::g()       // OK: brak sowa final
{
    //...
}
---------------
int final = 7;

struct Dx : Base {
    int final;

    int f() final
    {
        return final + ::final;
    }
};
---------------
struct Base {
    void f(int);
};

struct Derived : Base {
    void f(double);
};

void use(Derived d)
{
    d.f(1);  // wywouje Derived::f(double)
    Base& br = d
    br.f(1); // wywouje Base::f(int)
}
---------------
struct D2 : Base {
    using Base::f; // dodaje wszystkie f z Base do D2
    void f(double);
};

void use2(D2 d)
{
    d.f(1);        // wywouje D2::f(int), tzn. Base::f(int)
    Base& br = d
    br.f(1);       // wywouje Base::f(int)
}
---------------
struct B1 {
    void f(int);
};

struct B2 {
    void f(double);
};

struct D : B1, B2 {
    using B1::f;
    using B2::f;
    void f(char);
};

void use(D d)
{
    d.f(1);   // wywouje D::f(int), tzn. B1::f(int)
    d.f('a'); // wywouje D::f(char)
    d.f(1.0); // wywouje D::f(double), tzn. B2::f(double)
}
---------------
template<typename T>
struct Vector : std::vector<T> {
    using size_type = typename std::vector<T>::size_type;  // uycie typu rozmiaru wektora

    T& operator[](size_type i) { return this->at(i); }     // uycie dostpu kontrolowanego
    const T& operator[](size_type i) const { return this->at(i); }
};
---------------
Vector<int> v { 1, 2, 3, 5, 8 }; // bd: brak konstruktora z list inicjacyjn
---------------
template<typename T>
struct Vector : std::vector<T> {
    using size_type = typename std::vector<T>::size_type;  // uycie typu rozmiaru wektora

    using std::vector<T>::vector;                          // odziedziczenie konstruktorw wektora

    T& operator=[](size_type i) { return this->at(i); }    // uycie kontrolowanego dostpu
    const T& operator=(size_type i) const { return this->at(i); }
};

Vector<int> v { 1, 2, 3, 5, 8 }; // OK: uycie konstruktora z list inicjacyjn z std::vector
---------------
struct B1 {
    B1(int) { }
};

struct D1 : B1 {
    using B1::B1; // niejawnie deklaruje D1(int)
    string s;     // string ma domylny konstruktor
    int x;        // "zapomnielimy" zainicjowa x
};

void test()
{
    D1 d {6};     // ups: skadowa d.x jest niezainicjowana
    D1 e;         // bd: D1 nie ma domylnego konstruktora
}
---------------
struct D1 : B1 {
    D1(int i) : B1(i) { }
    string s; // typ string ma domylny konstruktor
    int x;    // "zapomnielimy" zainicjowa x
};
---------------
struct D1 : B1 {
    using B1::B1; // niejawnie deklaruje D1(int)
    int x {0};    // uwaga: skadowa x jest zainicjowana
};

void test()
{
    D1 d {6}; // d.x wynosi zero
}
---------------
class Expr {
public:
    Expr();            // konstruktor domylny
    Expr(const Expr&); // konstruktor kopiujcy
    virtual Expr* new_expr() =0;
    virtual Expr* clone() =0;
    //...
};
---------------
class Cond : public Expr {
public:
    Cond();
    Cond(const Cond&);
    Cond* new_expr() override { return new Cond(); }
    Cond* clone() override { return new Cond(*this); }
    //...
};
---------------
void user(Expr* p)
{
    Expr* p2 = p->new_expr();
    //...
}
---------------
void user2(Cond* pc, Addition* pa)
{
    Cond* p1 = pc->clone();
    Addition* p2 = pa->clone();
    //...
}
---------------
void user3(Cond* pc, Expr* pe)
{
    Cond* p1 = pc->clone();
    Cond* p2 = pe->clone();  // bd: funkcja Expr::clone() zwraca typ Expr*
    //...
}
---------------
class Shape {
public:
    virtual void rotate(int) { throw runtime_error{"Shape::rotate"}; } // nieeleganckie
    virtual void draw() const { throw runtime_error{"Shape::draw"}; }
    //...
};
---------------
Shape s; // bez sensu: bezksztatny ksztat
---------------
class Shape { // klasa abstrakcyjna
public:
    virtual void rotate(int) = 0;       // funkcja czysto wirtualna
    virtual void draw() const = 0;      // funkcja czysto wirtualna
    virtual bool is_closed() const = 0; // funkcja czysto wirtualna
    //...
    virtual ~Shape();                   // wirtualny
};
---------------
Shape s; // bd: zmienna abstrakcyjnej klasy Shape
---------------
class Point { /*...*/};

class Circle : public Shape {
public:
    Circle(Point p, int r);

    void rotate(int) override { }
    void draw() const override;
    bool is_closed() const override { return true; }
    //...
private:
    Point center;
    int radius;
};
---------------
class Polygon : public Shape { // klasa abstrakcyjna
public:
    bool is_closed() const override { return true; }
    //... funkcje draw i rotate nie s przesonite...
};

Polygon b {p1,p2,p3,p4}; // bd: deklaracja obiektu abstrakcyjnej klasy Polygon
---------------
class Irregular_polygon : public Polygon {
    list<Point> lp;
public:
    Irregular_polygon(initializer_list<Point>);

    void draw() const override;
    void rotate(int) override;
    //...
};

Irregular_polygon poly {p1,p2,p3,p4};  // zaoenie, e p1-p4 to zdefiniowane gdzie obiekty klasy Point
---------------
class Character_device {
public:
    virtual int open(int opt) = 0;
    virtual int close(int opt) = 0;
    virtual int read(char* p, int n) = 0;
    virtual int write(const char* p, int n) = 0;
    virtual int ioctl(int ...) = 0; // sterowanie urzdze wejcia i wyjcia

    virtual ~Character_device() { } // destruktor wirtualny
};
---------------
template<typename T>
class List {
public:
    void insert(T);
    T get();
    //...
private:
    struct Link { T val; Link* next; };

    struct Chunk {
        enum { chunk_size=15};
        Link v[chunk_size];
        Chunk* next;
    };

    Chunk* allocated;
    Link* free;
    Link* get_free();
    Link* head;
};
---------------
template<typename T>
void List<T>::insert(T val)
{
    Link* lnk = get_free();
    lnk->val = val;
    lnk->next = head;
    head = lnk;
}

template<typename T>
T List<T>::get()
{
    if (head == nullptr)
        throw Underflow{};  // Underflow to klasa wyjtkw

    Link* p= head;
    head = p->next;
    p->next = free;
    free = p;
    return p->val;
}
---------------
template<typename T>
typename List<T>::Link* List<T>::get_free()
{
    if (free == nullptr) {
        //... alokacja nowego fragmentu pamici i umieszczenie czy w licie free...
    }
    Link* p = free;
    free = free->next;
    return p;
}
---------------
template<typename T>
auto List<T>::get_free() -> Link*
{
    //...
}
---------------
template<typename T>
void would_be_meddler(List<T>* p)
{
    List<T>::Link* q=0;                     // bd: List<T>::Link jest prywatna
    //...
    q = p->free;                           // bd: List<T>::free jest prywatna
    //...
    if (List<T>::Chunk::chunk_size > 31) { // bd: List<T>::Chunk::chunk_size jest prywatna
        //...
    }
}
---------------
template<typename T>
struct Link2 {
    T val;
    Link2* next;
};

template<typename T>
class List {
private:
    Link2<T>* free;
    //...
};
---------------
template<typename T> class List;

template<typename T>
class Link3 {
    friend class List<T>; // tylko List<T> ma dostp do Link3<T>
    T val;
    Link3* next;
};
template<typename T>
class List {
private:
    Link3<T>* free;
    //...
};
---------------
class S {
public:
    int m1;
public:
    int m2;
};
---------------
class Buffer {
public:
    char& operator[](int i); // dostp kontrolowany
    //...
protected:
    char& access(int i);     // dostp niekontrolowany
    //...
};

class Circular_buffer : public Buffer {
public:
    void reallocate(char* p, int s); // zmienia lokalizacj i rozmiar
    //...
};

void Circular_buffer::reallocate(char* p, int s)// zmienia lokalizacj i rozmiar
{
    //...
    for (int i=0; i!=old_sz; ++i)
        p[i] = access(i);    // bez niepotrzebnego sprawdzania
    //...
}

void f(Buffer& b)
{
    b[3] = 'b';              // OK (kontrolowane)
    b.access(3) = 'c';       // bd: funkcja Buffer::access() jest chroniona
}
---------------
class Buffer {
protected:
    char a[128];
    //...
};

class Linked_buffer : public Buffer {
    //...
};

class Circular_buffer : public Buffer {
    //...
    void f(Linked_buffer* p)
    {
        a[0] = 0;    // OK: dostp do skadowej chronionej klasy Circular_buffer
        p->a[0] = 0; // bd: dostp do chronionej skadowej innego typu
    }
};
---------------
class X : public B { /*...*/};
class Y : protected B { /*...*/};
class Z : private B { /*...*/};
---------------
class XX : B { /*...*/};  // B jest baz prywatn
struct YY : B { /*...*/}; // B jest baz publiczn
---------------
struct B {
    int m;
    static int sm;
    //...
};

class D1 : public virtual B { /*...*/};
class D2 : public virtual B { /*...*/};
class D12 : public D1, private D2 { /*...*/};

D12* pd = new D12;
B* pb = pd;      // OK: dostpna przez D1
int i1 = pd->m; // OK: dostpna przez D1
---------------
class X1 : public B { /*...*/};
class X2 : public B { /*...*/};
class XX : public X1, public X2 { /*...*/};

XX* pxx = new XX;
int i1 = pxx->m;  // bd niejednoznacznoci: XX::X1::B::m czy XX::X2::B::m?
int i2 = pxx->sm; // OK: jest tylko jedna skadowa B::sm w obiekcie klasy XX (sm jest skadow statyczn)
---------------
class B {
private:
    int a;
protected:
    int b;
public:
    int c;
};

class D : public B {
public:
    using B::a; // bd: skadowa B::a jest prywatna
    using B::b; // sprawia, e skadowa B::b bdzie publicznie dostpna przez D
};
---------------
class BB : private B { // udostpnia B::b i B::c, ale nie B::a
public:
    using B::b;
    using B::c;
};
---------------
class Std_interface {
public:
    virtual void start() = 0;
    virtual void suspend() = 0;
    virtual void resume() = 0;
    virtual void quit() = 0;
    virtual void full_size() = 0;
    virtual void small() = 0;

    virtual ~Std_interface() {}
};
---------------
using Pstd_mem = void (Std_interface::*)(); // typ wskanik do skadowej

void f(Std_interface* p)
{
    Pstd_mem s = &Std_interface::suspend;   // wskanik do suspend()
    p->suspend();                           // bezporednie wywoanie
    p->*s();                                // wywoanie poprzez wskanik do skadowej
}
---------------
map<string,Std_interface*> variable;
map<string,Pstd_mem> operation;

void call_member(string var, string oper)
{
    (variable[var]->*operation[oper])(); // var.oper()
}
---------------
class Task {
    //...
    static void schedule();
};

void (*p)() = &Task::schedule;         // OK
void (Task::*pm)() = &Task::schedule;  // bd: zwyky wskanik przypisany
                                       // do wskanika do skadowej
---------------
struct C {
    const char* val;
    int i;

    void print(int x) { cout << val << x << '\n'; }
    int f1(int);
    void f2();
    C(const char* v) { val = v; }
};

using Pmfi = void (C::*)(int); // wskanik do funkcji skadowej struktury C przyjmujcej int
using Pm = const char*C::*;    // wskanik do danej skadowej char* struktury C

void f(C& z1, C& z2)
{
    C* p = &z2;
    Pmfi pf = &C::print;
    Pm pm = &C::val;
    z1.print(1);
    (z1.*pf)(2);
    z1.*pm = "nv1 ";
    p->*pm = "nv2 ";
    z2.print(3);
    (p->*pf)(4);
    pf = &C::f1; // bd: inny typ zwrotny
    pf = &C::f2; // bd: inny typ argumentu
    pm = &C::i;  // bd: rne typy
    pm = pf;     // bd: rne typy
}
---------------
class Text : public Std_interface {
public:
    void start();
    void suspend();
    //...
    virtual void print();
private:
    vector s;
};

void (Std_interface::* pmi)() = &Text::print;  // bd
void (Text::* pmt)() = &Std_interface::start;  // OK