Skip to main content

  | मौसम…

411 समाचार
Public archive edition · Attributed source reporting with original dates · AI drafts are excluded

411 REFERENCE · Wikibooks

More C++ Idioms/Inner Class

Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.

Inner Class Intent Implementing multiple interfaces without multiple inheritance and yet provide natural looking up-casting. Provide multiple implementations of the same interface in a single abstraction. Also Known As Motivation Signature of a virtual function in two independent interfaces provided by two independent class libraries may collide. It is a problem especially when a single class has to implement both the colliding functions in different ways depending upon the interface you consider. For example, class Base1 /// Provided by Moon { public: virtual int open (int) = 0; /* virtual */ ~Base1() {} // No polymorphic deletion allowed }; class Base2 /// Provided by Jupitor { public: virtual int open (int) = 0; /* virtual */ ~Base2() {} // No polymorphic deletion allowed }; class Derived : public Base1, public Base2 { public: virtual int open (int i) { // Call from which base class? return 0; } /* virtual */ ~Derived () {} }; The inner class idiom can help solve this problem. Solution and Sample Code Leaving the interface classes, Base1 and Base2 unchanged we can implement the Derived class as follows. #include <iostream> class Base1 /// Provided by Moon { public: virtual int open() = 0; /* virtual */ ~Base1() {} // No polymorphic deletion allowed }; class Base2 /// Provided by Jupitor { public: virtual int open() = 0; /* virtual */ ~Base2() {} // No polymorphic deletion allowed }; class Derived // Note no inheritance { class Base1_Impl; friend class Base1_Impl; class Base1_Impl : public Base1 // Note public inheritance { public: Base1_Impl(Derived* p) : parent_(p) {} int open() override { return parent_->base1_open(); } private: Derived* parent_; } base1_obj; // Note member object here. class Base2_Impl; friend class Base2_Impl; class Base2_Impl : public Base2 // Note public inheritance { public: Base2_Impl(Derived* p) : parent_(p) {} int open() override { return parent_->base2_open(); } private: Derived* parent_; } base2_obj; // Note member object here int base1_open() { return 111; } /// implement int base2_open() { return 222; } /// implement public: Derived() : base1_obj(this), base2_obj(this) {} Derived(Derived const&) : base1_obj(this), base2_obj(this) {} Derived(Derived&&) : base1_obj(this), base2_obj(this) {} Derived& operator=(Derived const&) { return *this; } Derived& operator=(Derived&&) { return *this; } operator Base1&() { return base1_obj; } /// convert to Base1& operator Base2&() { return base2_obj; } /// convert to Base2& }; /// class Derived int base1_open(Base1& b1) { return b1.open(); } int base2_open(Base2& b2) { return b2.open(); } int main(void) { Derived d; std::cout << base1_open(d) << std::endl; // Like upcasting in inheritance. std::cout << base2_open(d) << std::endl; // Like upcasting in inheritance. } Note the use of conversion operators in class Derived. (Derived class is really not a derived class!) The conversion operators allow conversion of Derived to Base1 even though they don't share inheritance relationship themselves! Use of member objects base1_obj and base2_obj eliminates the concern of object lifetime. Lifetime of member objects is same as that of the Derived object. Known Uses Related Idioms Interface Class Capability Query References Thinking in C++ Vol 2 - Practical Programming --- by Bruce Eckel. ja:More C++ Idioms/内部クラス(Inner Class)