SlideShare a Scribd company logo
C++ : наследование, часть 2 Дмитрий Штилерман, Рексофт
Краткое содержание второй части Public & protected interface . Случаи видимости наследования ( public, protected, private)  и их семантика. О тношения “has-a”  и  “is-implemented-by”. Композиция (aggregation). Делегирование ( delegation) . Изоляция ( insulation ).
Интерфейсы и реализация класса Дизайнер класса  B  в общем случае проектирует два разных интерфейса:  public & protected. Public interface   - множество всех  public members  B. Его клиенты - все классы, использующие  B.  Protected interface   - множество всех  protected members B . Его клиенты - классы, производные от  B. Как насчет п онятия private interface?  Private  members  класса  B  являются частью его  реализации   (implementation),  а не интерфейса.
Public & protected interface -  пример class Shape  {   public:    virtual void redraw() = 0;   protected:   void default_redraw();  }; class Tool  {   public:   void applyTo(Shape* pShape)   {/*…*/ pShape->redraw();}  }; class Rectangle : public Shape  {   public:   virtual void redraw()   {/*…*/ default_redraw();}  }; Shape:: redraw() -  часть  public interface . Им могут пользоваться любые классы и функции. Shape::default_redraw() - часть  protected interface. Им могут пользоваться только производные классы.
Public & protected interface -  обозначения I public (B) - class B public interface. I protected (B) - class B protected interface. I(B) -  class B complete interface. I(B)     I public (B)    I protected (B) I(B,A) - part of class B interface inherited from its base class A. I(B,*) - part of class B interface inherited from all its base classes. I(B,B) - part of class B interface declared inside B itself (“own” interface). I x (B)    I x (B,*)    I x (B,B) R(B) - class B implementation.
Public inheritance  class B  {   public: void f_public();   protected: void f_protected();  }; class D : public B  {   public: void g_public();   protected: void g_protected();  }; I public (D) = I public (B)    I public (D,D) I protected (D) = I protected  (B)    I protected  (D,D) I(D) = I( B )    I(D,D) I public (B) = {B::f_public()} I protected (B) =  {B::f_protected()} I public (D) = {B::f_public(), D::g_public()} I protected (D) =  {B::f_protected(), D::g_protected()} Public и  protected  интерфейсы  B  добавляются в соответствующие интерфейсы  D.
Protected inheritance  class B  {   public: void f_public();   protected: void f_protected();  }; class D : protected B  {   public: void g_public();   protected: void g_protected();  }; I public (B) = {B::f_public()} I protected (B) =  {B::f_protected()} I public (D) = {D::g_public()} I protected (D) =  { B::f_public(),  B::f_protected(), D::g_protected()} I public (D) = I public (D,D) I protected (D) = I(B)    I protected  (D,D) I(D) = I( B )    I(D,D) Public и  protected  интерфейсы  B  добавляются в  protected  интерфейс  D.
Private inheritance  class B  {   public: void f_public();   protected: void f_protected();  }; class D : private B  {   public: void g_public();   protected: void g_protected();  }; I public (B) = {B::f_public()} I protected (B) =  {B::f_protected()} I public (D) = {D::g_public()} I protected (D) =  {D::g_protected()} I public (D) = I public (D,D) I protected (D) = I protected  (D,D) I(D,*) = I( D,B ) =   I(D) = I(D,D) R(D)    I(B) (!!!) Public и  protected  интерфейсы  B  становятся частью реализации  D.
Когда какое наследование  возможно  использовать? Public : когда хотим интерфейсы базового класса раздать всем своим клиентам. I(Derived)    I(Base). Protected :  когда хотим интерфейсы базового класса раздать своим производным классам (клиентам  protected  интерфейса). I protected (Derived)    I(Base). Private :  когда хотим воспользоваться интерфейсами базового класса сами, т.е. включить их в нашу реализацию. R(Derived)    I(Base).
Почему обычно  не нужно  использовать  наследование, отличное от  public? Любое  наследование соответствует отношению “is-a”. Отношение “is-a” концептуально (на уровне анализа) является частью интерфейса класса и определяет тип объекта. Изменяя видимость наследования мы меняем видимость отношения “is-a”  для клиентов класса . На практике  очень редко встречается ситуация, когда видимость отношения “is-a” различна для разных клиентов.
Отношение “has-a” - к омпозиция (aggregation) class Caption {…}; class Label {…}; class Button {…}; class MessageBox  {   Caption m_caption;   Label m_label;   Button m_buttonOK;   Button m_buttonCancel;   }; Отношение “has-a”  на практике всегда реализуется через композицию ( aggregation) .  See also: Composite pattern. Отношение “has-a” концептуально отлично от отношения “is-a”. NB:  не стоит реализовывать отношение  “has-a”  через  public data members!  Лучше делать это через  accessor methods , внимательно обдумывая интерфейс.
Отношени е  “is-implemented-by” - делегирование (delegation) Концептуально отношение “is-implemented-by”  всегда является частью реализации. Толкования слова “делегирование” из словаря: “передача прав и ответственности подчиненному”, “перед а ча полномочий” . Делегирование - частный случай использования. Что происходит с интерфейсами? В случае делегирования на уровне  public  или  protected  методов мы делаем так, что  I(A)    I public (B),  но при этом  B  не является базовым классом  A. В случае делегирования на уровне  private  методов делегирование является частью реализации. class A  {   B m_b;   void f()   {m_b.f();}   void g()   {m_b.g();}  }; class B  {   public:   void f()   {…}   void g()   {…}  };
И золяция ( insulation ) Изоляция ( insulation) - разновидность  инкапсуляции, когда клиенты класса полностью изолированы от деталей реализации. Изоляция - разновидность композиции (с точки зрения структуры). Синонимы: метафора  “handle-body”, метафора “letter-envelope”. John Lakos, “Large-Scale C+ Software Design” //  Файл  gadget.h class GadgetImpl; class Gadget  {   private:   GadgetImpl* m_pImpl;   public:   Gadget();    void f();  }; //  Файл  gadget.cpp #include “gadget.h” class GadgetImpl  {   public:   void f() {…}  }; Gadget::Gadget()  {m_pImpl = new GadgetImpl;}  void Gadget::f()  {m_pImpl->f();}
P rivate  inheritance  как инкапсуляция базового класса Хотим использовать protected  интерфейс класса  B     в ынуждены от него наследовать. Отношение “is-implemented-by”  есть часть реализации    наследование д.б.  private . Вопрос: Зачем такое извращение м.б. нужно? Ответ: Когда мы хотим сделать частью реализации сам базовый класс! class A : private B  {   void f()   {B::f();}   void g()   {B::g();}  }; class B  {   public:   void f()   {…}   protected:    void g()   {…}  };
P rivate  inheritance  как упаковка общей части реализации Хотим абстрагировать для нескольких наших классов их общую реализацию, выделив ее в отдельный класс. Не хотим, чтобы ей пользовался кто-то другой. По каким-то причинам не хотим или не можем использовать изоляцию. Часто встречающаяся уважительная причина - реализация  шаблонов . class GadgetBase  {   protected:   GadgetBase();   void f()   {/*  Очень умный алгоритм  */}  }; template<class T> class Gadget : private GadgetBase  {   public:   void f()   {GadgetBase::f();}  };
Подведение итогов Основной вопрос философии Что хотел сказать автор своим дизайном? Правила правой руки Отношение “is-a”:  public inheritance Отношение “has-a”:  aggregation Отношение “is-implemented-by”: Изоляция не нужна   или невозможна:  aggregation Изоляция нужна и возможна:   insulation Желательна упаковка общей реализации нескольких классов:  private inheritance
Продолжение в следующей серии Множественное наследование . Какое оно бывает? Что оно значит? Как с ним бороться?

More Related Content

PDF
俄语GOST标准,技术规范,法律,法规,中文英语,目录编号RG 4103
PDF
Linux Commands
PDF
Hsc bangla 2nd only for dinajpur
PDF
とある高専出身の過去現在未来
PDF
Ведение документации в perl6: POD, да не тот !
PDF
Postgre Sql 8 4
PDF
Gorm
PPT
OO Design with C++: 6. Templates & Patterns
俄语GOST标准,技术规范,法律,法规,中文英语,目录编号RG 4103
Linux Commands
Hsc bangla 2nd only for dinajpur
とある高専出身の過去現在未来
Ведение документации в perl6: POD, да не тот !
Postgre Sql 8 4
Gorm
OO Design with C++: 6. Templates & Patterns

Similar to OO Design with C++: 2. Inheritance, part 2 (20)

PPT
OO Design with C++: 1. Inheritance, part 1
PDF
Unittests
PDF
Cisco collaboration. 8_oktiabria_biznes-trek_litsenzirovanie
PDF
Обеспечение безопасности web приложений
PDF
Minsk Web Appl 190509
PDF
IBM Jazz - A New Approach For Software Development (In Russian)
PDF
Jazz – открытая платформа разработки ПО
PPTX
Taleb's Black Swan - SG 20090520
PDF
Управление рисками ИБ: отдельные практические аспекты
PPTX
Minsk Jazz 190509 Templ
PDF
Библейские истории: Животные
PDF
Customer Profiling&Targeted Advertisement
PDF
Social Bookmarks, Folksonomies–Complex Networks
PPT
Hackday Ml
PDF
тупицын Ec2 Rootconf2009
PPTX
vSphere Launch Business Keynote - Москва, 26 мая
DOC
kakvo e sniffer
PDF
Java For Digitally Signing Documents In Web Book - Svetlin Nakov
PDF
IP в телевидении или телевидение в IP?
PDF
за Ruby
OO Design with C++: 1. Inheritance, part 1
Unittests
Cisco collaboration. 8_oktiabria_biznes-trek_litsenzirovanie
Обеспечение безопасности web приложений
Minsk Web Appl 190509
IBM Jazz - A New Approach For Software Development (In Russian)
Jazz – открытая платформа разработки ПО
Taleb's Black Swan - SG 20090520
Управление рисками ИБ: отдельные практические аспекты
Minsk Jazz 190509 Templ
Библейские истории: Животные
Customer Profiling&Targeted Advertisement
Social Bookmarks, Folksonomies–Complex Networks
Hackday Ml
тупицын Ec2 Rootconf2009
vSphere Launch Business Keynote - Москва, 26 мая
kakvo e sniffer
Java For Digitally Signing Documents In Web Book - Svetlin Nakov
IP в телевидении или телевидение в IP?
за Ruby
Ad

More from Dmitry Stillermann (6)

PPTX
DiSC Model in Practice
PPTX
Как расти самому, помогая расти другим — практическое применение Management T...
PPT
OO Design with C++: 4. Design Principles, part 1
PPT
OO Design with C++: 5. Design Principles, part 2
PPT
OO Design with C++: 3. Inheritance, part 3
PPT
OO Design with C++: 0. Intro
DiSC Model in Practice
Как расти самому, помогая расти другим — практическое применение Management T...
OO Design with C++: 4. Design Principles, part 1
OO Design with C++: 5. Design Principles, part 2
OO Design with C++: 3. Inheritance, part 3
OO Design with C++: 0. Intro
Ad

Recently uploaded (20)

PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
Unlocking AI with Model Context Protocol (MCP)
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PPTX
Programs and apps: productivity, graphics, security and other tools
PPTX
Spectroscopy.pptx food analysis technology
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Electronic commerce courselecture one. Pdf
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PDF
Approach and Philosophy of On baking technology
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PPTX
sap open course for s4hana steps from ECC to s4
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Review of recent advances in non-invasive hemoglobin estimation
Unlocking AI with Model Context Protocol (MCP)
Digital-Transformation-Roadmap-for-Companies.pptx
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Programs and apps: productivity, graphics, security and other tools
Spectroscopy.pptx food analysis technology
Spectral efficient network and resource selection model in 5G networks
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
Advanced methodologies resolving dimensionality complications for autism neur...
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Electronic commerce courselecture one. Pdf
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Approach and Philosophy of On baking technology
Reach Out and Touch Someone: Haptics and Empathic Computing
The Rise and Fall of 3GPP – Time for a Sabbatical?
Agricultural_Statistics_at_a_Glance_2022_0.pdf
sap open course for s4hana steps from ECC to s4
Profit Center Accounting in SAP S/4HANA, S4F28 Col11

OO Design with C++: 2. Inheritance, part 2

  • 1. C++ : наследование, часть 2 Дмитрий Штилерман, Рексофт
  • 2. Краткое содержание второй части Public & protected interface . Случаи видимости наследования ( public, protected, private) и их семантика. О тношения “has-a” и “is-implemented-by”. Композиция (aggregation). Делегирование ( delegation) . Изоляция ( insulation ).
  • 3. Интерфейсы и реализация класса Дизайнер класса B в общем случае проектирует два разных интерфейса: public & protected. Public interface - множество всех public members B. Его клиенты - все классы, использующие B. Protected interface - множество всех protected members B . Его клиенты - классы, производные от B. Как насчет п онятия private interface? Private members класса B являются частью его реализации (implementation), а не интерфейса.
  • 4. Public & protected interface - пример class Shape { public: virtual void redraw() = 0; protected: void default_redraw(); }; class Tool { public: void applyTo(Shape* pShape) {/*…*/ pShape->redraw();} }; class Rectangle : public Shape { public: virtual void redraw() {/*…*/ default_redraw();} }; Shape:: redraw() - часть public interface . Им могут пользоваться любые классы и функции. Shape::default_redraw() - часть protected interface. Им могут пользоваться только производные классы.
  • 5. Public & protected interface - обозначения I public (B) - class B public interface. I protected (B) - class B protected interface. I(B) - class B complete interface. I(B)  I public (B)  I protected (B) I(B,A) - part of class B interface inherited from its base class A. I(B,*) - part of class B interface inherited from all its base classes. I(B,B) - part of class B interface declared inside B itself (“own” interface). I x (B)  I x (B,*)  I x (B,B) R(B) - class B implementation.
  • 6. Public inheritance class B { public: void f_public(); protected: void f_protected(); }; class D : public B { public: void g_public(); protected: void g_protected(); }; I public (D) = I public (B)  I public (D,D) I protected (D) = I protected (B)  I protected (D,D) I(D) = I( B )  I(D,D) I public (B) = {B::f_public()} I protected (B) = {B::f_protected()} I public (D) = {B::f_public(), D::g_public()} I protected (D) = {B::f_protected(), D::g_protected()} Public и protected интерфейсы B добавляются в соответствующие интерфейсы D.
  • 7. Protected inheritance class B { public: void f_public(); protected: void f_protected(); }; class D : protected B { public: void g_public(); protected: void g_protected(); }; I public (B) = {B::f_public()} I protected (B) = {B::f_protected()} I public (D) = {D::g_public()} I protected (D) = { B::f_public(), B::f_protected(), D::g_protected()} I public (D) = I public (D,D) I protected (D) = I(B)  I protected (D,D) I(D) = I( B )  I(D,D) Public и protected интерфейсы B добавляются в protected интерфейс D.
  • 8. Private inheritance class B { public: void f_public(); protected: void f_protected(); }; class D : private B { public: void g_public(); protected: void g_protected(); }; I public (B) = {B::f_public()} I protected (B) = {B::f_protected()} I public (D) = {D::g_public()} I protected (D) = {D::g_protected()} I public (D) = I public (D,D) I protected (D) = I protected (D,D) I(D,*) = I( D,B ) =  I(D) = I(D,D) R(D)  I(B) (!!!) Public и protected интерфейсы B становятся частью реализации D.
  • 9. Когда какое наследование возможно использовать? Public : когда хотим интерфейсы базового класса раздать всем своим клиентам. I(Derived)  I(Base). Protected : когда хотим интерфейсы базового класса раздать своим производным классам (клиентам protected интерфейса). I protected (Derived)  I(Base). Private : когда хотим воспользоваться интерфейсами базового класса сами, т.е. включить их в нашу реализацию. R(Derived)  I(Base).
  • 10. Почему обычно не нужно использовать наследование, отличное от public? Любое наследование соответствует отношению “is-a”. Отношение “is-a” концептуально (на уровне анализа) является частью интерфейса класса и определяет тип объекта. Изменяя видимость наследования мы меняем видимость отношения “is-a” для клиентов класса . На практике очень редко встречается ситуация, когда видимость отношения “is-a” различна для разных клиентов.
  • 11. Отношение “has-a” - к омпозиция (aggregation) class Caption {…}; class Label {…}; class Button {…}; class MessageBox { Caption m_caption; Label m_label; Button m_buttonOK; Button m_buttonCancel; }; Отношение “has-a” на практике всегда реализуется через композицию ( aggregation) . See also: Composite pattern. Отношение “has-a” концептуально отлично от отношения “is-a”. NB: не стоит реализовывать отношение “has-a” через public data members! Лучше делать это через accessor methods , внимательно обдумывая интерфейс.
  • 12. Отношени е “is-implemented-by” - делегирование (delegation) Концептуально отношение “is-implemented-by” всегда является частью реализации. Толкования слова “делегирование” из словаря: “передача прав и ответственности подчиненному”, “перед а ча полномочий” . Делегирование - частный случай использования. Что происходит с интерфейсами? В случае делегирования на уровне public или protected методов мы делаем так, что I(A)  I public (B), но при этом B не является базовым классом A. В случае делегирования на уровне private методов делегирование является частью реализации. class A { B m_b; void f() {m_b.f();} void g() {m_b.g();} }; class B { public: void f() {…} void g() {…} };
  • 13. И золяция ( insulation ) Изоляция ( insulation) - разновидность инкапсуляции, когда клиенты класса полностью изолированы от деталей реализации. Изоляция - разновидность композиции (с точки зрения структуры). Синонимы: метафора “handle-body”, метафора “letter-envelope”. John Lakos, “Large-Scale C+ Software Design” // Файл gadget.h class GadgetImpl; class Gadget { private: GadgetImpl* m_pImpl; public: Gadget(); void f(); }; // Файл gadget.cpp #include “gadget.h” class GadgetImpl { public: void f() {…} }; Gadget::Gadget() {m_pImpl = new GadgetImpl;} void Gadget::f() {m_pImpl->f();}
  • 14. P rivate inheritance как инкапсуляция базового класса Хотим использовать protected интерфейс класса B  в ынуждены от него наследовать. Отношение “is-implemented-by” есть часть реализации  наследование д.б. private . Вопрос: Зачем такое извращение м.б. нужно? Ответ: Когда мы хотим сделать частью реализации сам базовый класс! class A : private B { void f() {B::f();} void g() {B::g();} }; class B { public: void f() {…} protected: void g() {…} };
  • 15. P rivate inheritance как упаковка общей части реализации Хотим абстрагировать для нескольких наших классов их общую реализацию, выделив ее в отдельный класс. Не хотим, чтобы ей пользовался кто-то другой. По каким-то причинам не хотим или не можем использовать изоляцию. Часто встречающаяся уважительная причина - реализация шаблонов . class GadgetBase { protected: GadgetBase(); void f() {/* Очень умный алгоритм */} }; template<class T> class Gadget : private GadgetBase { public: void f() {GadgetBase::f();} };
  • 16. Подведение итогов Основной вопрос философии Что хотел сказать автор своим дизайном? Правила правой руки Отношение “is-a”: public inheritance Отношение “has-a”: aggregation Отношение “is-implemented-by”: Изоляция не нужна или невозможна: aggregation Изоляция нужна и возможна: insulation Желательна упаковка общей реализации нескольких классов: private inheritance
  • 17. Продолжение в следующей серии Множественное наследование . Какое оно бывает? Что оно значит? Как с ним бороться?

Editor's Notes

  • #2: Public vs. protected interface - two types of clients {part. Meyers1.41}. Containment as &amp;quot;has-a&amp;quot; or &amp;quot;is-implemented-via&amp;quot; relationship {Meyers1.40} Private inheritance - reasons of use instead of containment {Meyers1.42}