, , : typeid static_type_info(type) // typeid typeid ptr_type_info(pointer) // typeid typeid ref_type_info(reference) // typeid pointer ptr_cast(type,pointer) // reference ref_cast(type,reference) // , "", . , , ptr_cast() ref_cast(). , . , . , , (, - -), : static_type_info(), ptr_type_info() ref_type_info(). typeid. set slist_set, typeid . typeid . , , typeid get_type_info(): class typeid { friend class Type_info; private: const Type_info* id; public: typeid(const Type_info* p) : id(p) { } const Type_info* get_type_info() const { return id; } int operator==(typeid i) const ; }; get_type_info() (const) Type_info typeid. , : , . , . Type_info typeid , . , . 13.5.2 Type_info Type_info ptr_cast(); : class Type_info { const char* n; // const Type_info** b; // public: Type_info(const char* name, const Type_info* base[]); const char* name() const; Base_iterator bases(int direct=0) const; int same(const Type_info* p) const; int has_base(const Type_info*, int direct=0) const; int can_cast(const Type_info* p) const; static const Type_info info_obj; virtual typeid get_info() const; static typeid info(); }; Type_info . Type_info, . , , , , , . Type_info . , Type_info, . const char* Type_info::name() const { return n; } int Type_info::same(const Type_info* p) const { return this==p || strcmp(n,p->n)==0; } int Type_info::can_cast(const Type_info* p) const { return same(p) || p->has_base(this); } bases() has_base(). bases() , Type_info, has_base() . direct, , (direct=0), (direct=1). , , get_info() info() Type_info. . . . , , . has_base() Type_info . , , , , , . class base_iterator { short i; short alloc; const Type_info* b; public: const Type_info* operator() (); void reset() { i = 0; } base_iterator(const Type_info* bb, int direct=0); ~base_iterator() { if (alloc) delete[] (Type_info*)b; } }; , (direct==0) (direct==1). base_iterator::base_iterator(const Type_info* bb, int direct) { i = 0; if (direct) { // b = bb; alloc = 0; return; } // : // int n = b = new const Type_info*[n+1]; // b alloc = 1; return; } const Type_info* base_iterator::operator() () { const Type_info* p = &b[i]; if (p) i++; return p; } : #define static_type_info(T) T::info() #define ptr_type_info(p) ((p)->get_info()) #define ref_type_info(r) ((r).get_info()) #define ptr_cast(T,p) \ (T::info()->can_cast((p)->get_info()) ? (T*)(p) : 0) #define ref_cast(T,r) \ (T::info()->can_cast((r).get_info()) \ ? 0 : throw Bad_cast(T::info()->name()), (T&)(r)) , Bad_cast (_) : class Bad_cast { const char* tn; // ... public: Bad_cast(const char* p) : tn(p) { } const char* cast_to() { return tn; } // ... }; $$4.7 , . , , . . , , . , ptr_cast(), . 13.5.3  , , . , . set slist_set $$13.3 , . , set -, : class set { public: static const Type_info info_obj; virtual typeid get_info() const; static typeid info(); // ... }; set set::info_obj, : const Type_info set::info_obj("set",0); : typeid set::get_info() const { return &info_obj; } typeid set::info() { return &info_obj; } typeid slist_set::get_info() const { return &info_obj; } typeid slist_set::info() { return &info_obj; } get_info() ref_type_info() ptr_type_info(), info() - static_type_info(). , Type_info , , . slist_set: class slist_set : public set, private slist { // ... public: static const Type_info info_obj; virtual typeid get_info() const; static typeid info(); // ... }; static const Type_info* slist_set_b[] = { &set::info_obj, &slist::info_obj, 0 }; const Type_info slist_set::info_obj("slist_set",slist_set_b); typeid slist_set::get_info() const { return &info_obj; } typeid slist_set::info() { return &info_obj; } 13.5.4  Type_info , . Type_info - info() get_info(), , , Type_info . , Type_info, , dynamic_type() static_type(). : struct Member_info { char* name; Type_info* tp; int offset; }; class Map_info : public Type_info { Member_info** mi; public: static const Type_info info_obj; virtual typeid get_info() const; static typeid info(); // }; Type_info . , , . , - , ++, . 13.5.5  , : -, - , . . , , , . ++. , . Shape $$1.2.5. rotate : void rotate(const Shape& s) // // { if (ref_type_info(s)==static_type_info(Circle)) { // } else if (ref_type_info(s)==static_type_info(Triangle)) { // } else if (ref_type_info(s)==static_type_info(Square)) { // } // ... } , - . : Circle , (, (Circle) , , , ). , , , . , . , ptr_cast(), is_base(), has_base() Type_info. : void f(dialog_box& db) { if (is_base(&db,dbox_w_str)) { // db // dbox_w-str? dbox_w_str* dbws = (dbox_w_str*) &db; // ... } // ... } ptr_cast ($$13.5) , if, , . , , , , : class D; class B; void g(B* pb) { if (is_base(pb,D)) { D* pb = (D*)pb; // ... } // ... } D: class D : public A, public B { // ... }; , .. pb D* . ptr_cast() , , . , , . 13.6  ($$13.3) ($$13.4), , . . , , , , , .. , , , . , , . . , , ? , , .. , . , , . , "" . , , . "" T: class container { public: struct Bad_operation { // const char* p; Bad_operation(const char* pp) : p(pp) { } }; virtual void put(const T*) { throw Bad_operation("container::put"); } virtual T* get() { throw Bad_operation("container::get"); } virtual T*& operator[](int) { throw Bad_operation("container::[](int)"); } virtual T*& operator[](const char*) { throw Bad_operation("container::[](char*)"); } // ... }; - , , , , , . : , , . , : class slist_container : public container, private slist { public: void put(const T*); T* get(); T*& operator[](int) { throw Bad_operation("slist::[](int)"); } T*& operator[](const* char) { throw Bad_operation("slist::[](char*)"); } // ... }; . , , container: class vector_container : public container, private vector { public: T*& operator[](int); T*& operator[](const char*); // ... }; , : void f() { slist_container sc; vector_container vc; // ... } void user(container& c1, container& c2) { T* p1 = c1.get(); T* p2 = c2[3]; // c2.get() c1[3] // ... } ($$13.5) ($$9). : void user2(container& c1, container& c2) /* , - */ { try { T* p1 = c1.get(); T* p2 = c2[3]; // ... } catch(container::Bad_operation& bad) { // ! // ? } } : void user3(container& c1, container& c2) /* , */ { slist* sl = ptr_cast(slist_container,&c1); vector* v = ptr_cast(vector_container, &c2); if (sl && v) { T* p1 = c1.get(); T* p2 = c2[3]; // ... } else { // ! // ? } } , , "" . , . , . , , , , , , . , , . 13.7  , , . " " . , . , : , . . , , , . , , , , . , .. , : , , . , : class filter { public: class Retry { public: virtual const char* message() { return 0; } }; virtual void start() { } virtual int retry() { return 2; } virtual int read() = 0; virtual void write() { } virtual void compute() { } virtual int result() = 0; }; , . : int main_loop(filter* p) { for (;;) { try { p->start(); while (p->read()) { p->compute(); p->write(); } return p->result(); } catch (filter::Retry& m) { cout << m.message() << '\n'; int i = p->retry(); if (i) return i; } catch (...) { cout << "Fatal filter error\n"; return 1; } } } : class myfilter : public filter { istream& is; ostream& os; char c; int nchar; public: int read() { is.get(c); return is.good(); } void compute() { nchar++; }; int result() { os << nchar << "characters read\n"; return 0; } myfilter(istream& ii, ostream& oo) : is(ii), os(oo), nchar(0) { } }; : int main() { myfilter f(cin,cout); return main_loop(&f); } , , , . , . , , , . , , , scrollbar ($$12.2.5) dialog_box ($$13.4). . 13.8  - "" . - , , . . , , . , , . . Splist $$8.3.2: template<class T> class Splist : private Slist<void*> { public: void insert(T* p) { Slist<void*>::insert(p); } void append(T* p) { Slist<void*>::append(p); } T* get() { return (T*) Slist<void*>::get(); } }; Splist void* , . , -. , , - , . , , , ($$13.3), 13.9. , - . . , .. , , ? " ", ( Window): class Window { // ... virtual void draw(); }; class Cowboy { // ... virtual void draw(); }; class CowboyWindow : public Cowboy, public Window { // ... }; CowboyWindow . , , Window Cowboy, , Window Cowboy . CowboyWindow, - . , CowboyWindow: Cowboy::draw() Window::draw(). CowboyWindow draw(), Cowboy Window CowboyWindow, CowboyWindow () Cowboy::draw(), Window_draw(). - draw() , , , draw() . , , CowboyWindow Cowboy::draw() Window::draw() . Cowboy Window. draw() , Cowboy Window : class CCowboy : public Cowboy { virtual int cow_draw(int) = 0; void draw() { cow_draw(i); } // Cowboy::draw }; class WWindow : public Window { virtual int win_draw() = 0; void draw() { win_draw(); } // Window::draw }; CCowboy WWindow CowboyWindow cow_draw() win_draw: class CowboyWindow : public CCowboy, public WWindow { // ... void cow_draw(); void win_draw(); }; , , draw() . , , , . , . , , . , , , . ( : ). , . - , , . , , , : -, - . , , , .. - CCowboy::draw() WWindow_draw , . , , . . , . vector $$1.4. , , . , 0..size-1, , , : void f() { vector v(10); // [0:9] // v [1:10]: for (int i = 1; i<=10; i++) { v[i-1] = ... // } // ... } vec c : class vec : public vector { int lb; public: vec(int low, int high) : vector(high-low+1) { lb=low; } int& operator[](int i) { return vector::operator[](i-lb); } int low() { return lb; } int high() { return lb+size() - 1; } }; vec , : void g() { vec v(1,10); // [1:10] for (int i = 1; i<=10; i++) { v[i] = ... } // ... } , vec . , , ++ ($$12.1.4) ++. 13.9  . , , , . , - , , ( set), . , , . . , , , . , ($$13.10). , . , , , . , , : , , , . . , . , , , , . string $$7.6. , . , . set $$13.3. , ? set ->: class set_handle { set* rep; public: set* operator->() { return rep; } set_handler(set* pp) : rep(pp) { } }; , set_handle set& set*, : void my(set_handle s) { for (T* p = s->first(); p; p = s->next()) { // ... } // ... } void your(set_handle s) { for (T* p = s->first(); p; p = s->next()) { // ... } // ... } void user() { set_handle sl(new slist_set); set_handle v(new vector_set v(100)); my(sl); your(v); my(v); your(sl); } set set_handle , : class set { friend class set_handle; protected: int handle_count; public: virtual void insert(T*) = 0; virtual void remove(T*) = 0; virtual int is_member(T*) = 0; virtual T* first() = 0; virtual T* next() = 0; set() : handle_count(0) { } }; set, set_handle: class set_handle { set* rep; public: set* operator->() { return rep; } set_handle(set* pp) : rep(pp) { pp->handle_count++; } set_handle(const set_handle& r) : rep(r.rep) { rep->handle_count++; } set_handle& operator=(const set_handle& r) { rep->handle_count++; if (--rep->handle_count == 0) delete rep; rep = r.rep; return *this; } ~set_handle() { if (--rep->handle_count == 0) delete rep; } }; set set_handle, set. . , , , . , , , . : class set_handle { set* rep; public: // ... set* get_rep() { return rep; } void bind(set* pp) { pp->handle_count++; if (--rep->handle_count == 0) delete rep; rep = pp; } }; set_handle , - . - , . . , . : template<class T> class handle { T* rep; public: T* operator->() { return rep; } // ... }; "" . , , , . , ($$13.10). -> - . , : template<class T> class Xhandle { T* rep; int count; public: T* operator->() { count++; return rep; } // ... }; , , . , . , , : class set_controller { set* rep; // ... public: lock(); unlock(); virtual void insert(T* p) { lock(); rep->insert(p); unlock(); } virtual void remove(T* p) { lock(); rep->remove(p); unlock(); } virtual int is_member(T* p) { return rep->is_member(p); } virtual T* first() { return rep->first(); } virtual T* next() { return rep->next(); } // ... }; - ( ), . , set . , , , -. , , . ,