home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #20 / NN_1992_20.iso / spool / comp / lang / cplus / 13360 < prev    next >
Encoding:
Text File  |  1992-09-08  |  2.7 KB  |  82 lines

  1. Path: sparky!uunet!igor!thor!rmartin
  2. From: rmartin@thor.Rational.COM (Bob Martin)
  3. Newsgroups: comp.lang.c++
  4. Subject: Re: Avoiding returning references to Temporaries
  5. Message-ID: <rmartin.715870053@thor>
  6. Date: 7 Sep 92 12:47:33 GMT
  7. References: <lakldtINN17n@alnitak.usc.edu>
  8. Sender: news@Rational.COM
  9. Lines: 71
  10.  
  11. coller@alnitak.usc.edu (Lee D. Coller) writes:
  12. [...]
  13.  
  14. |The idea is that the member function D::getA() would be able to construct a
  15. |B or C and return it to the caller as an A.  Because of the semantics, most
  16. |likely D::getA() will have to create a temporary, so just returning a
  17. |reference to some pre-existing B or C will not work.
  18.  
  19. [...]
  20.  
  21. |The best solution I could come up with is to create another class to handle
  22. |managing a pointer to A such as the following.
  23.  
  24. [...example removed...]
  25.  
  26. |My question is, I would like to be able to do this without having A handle
  27. |reference counting.  Can anyone think of a good method?  Am I overlooking
  28. |some simple, elegant solution?  Also, is this what is referred to as a
  29. |"Smart pointer class?"
  30.  
  31. Take a look at "Advanced C++ Programming Styles and Idioms" by James
  32. O. Coplien in the section entitled "Envelope Classes and Delegated
  33. Polymorphism".  Here he talks about your problem and provides a
  34. solution.
  35.  
  36. The idea is to provide class A with a A* member, and a member
  37. functions that can determine whether a B or C is needed.  The needed
  38. class is placed in the A* pointer of the A object.  All other method
  39. calls of the A objects are explicitly deferred to the A* object.
  40.  
  41. For example:
  42.  
  43. class A
  44. {
  45.   public:
  46.      A() {itsA = 0;}
  47.      A(some criteria)
  48.      {
  49.        if (some criterion)
  50.          itsA = new B(...);
  51.        else
  52.          itsA = new C(...);
  53.      }
  54.  
  55.      virtual ~A() {delete itsA;}
  56.  
  57.      virtual int DoSomething(int x) {return itsA->DoSomething(x);}
  58.  
  59.   private:
  60.      A* itsA;
  61. };
  62.  
  63. class B : public A { public: B(); int DoSomething(int);};
  64. class C : public A { public: C(); int DoSomething(int);};
  65.  
  66. Now, whenever you construct an A object, whether from the heap, or on
  67. the stack, or even statically; if you supply a criterion, the
  68. appropriate B or C will be silently constructed and saved by the A
  69. object.  When you invoke the methods of A (DoSomething), those methods
  70. are simply deferred to the saved B or C object.  When the A object is
  71. destructed, the B or C is also automatically destroyed.
  72.  
  73. This method works well, but has one glaring fault.  A must know about
  74. B and C.  If more derivatives of A are needed later, A must change to
  75. support them in its constructor.  
  76.  
  77. --
  78. Robert Martin                        Training courses offered in:
  79. R. C. M. Consulting                       Object Oriented Analysis
  80. 2080 Cranbrook Rd.                        Object Oriented Design
  81. Green Oaks, Il 60048 (708) 918-1004       C++
  82.