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

  1. Path: sparky!uunet!usc!news
  2. From: coller@alnitak.usc.edu (Lee D. Coller)
  3. Newsgroups: comp.lang.c++
  4. Subject: Avoiding returning references to Temporaries
  5. Date: 6 Sep 1992 12:02:21 -0700
  6. Organization: University of Southern California, Los Angeles, CA
  7. Lines: 81
  8. Sender: coller@alnitak.usc.edu (Lee D. Coller)
  9. Distribution: world
  10. Message-ID: <lakldtINN17n@alnitak.usc.edu>
  11. NNTP-Posting-Host: alnitak.usc.edu
  12.  
  13. The following classes represent I problem I have encountered.
  14.  
  15. class A {
  16. public:
  17.     void func() = 0;
  18. };
  19.  
  20. class B : public A {
  21. private:
  22.     int _i;
  23. public:
  24.     void func();
  25. };
  26.  
  27. class C: public B {
  28. private:
  29.     double _d;
  30. public:
  31.     void func();
  32. };
  33.  
  34. class D {
  35. private:
  36.     /* some information from which to construct a B or C */
  37. public:
  38.     A getA() const;        // ideally
  39. };
  40.  
  41. The idea is that the member function D::getA() would be able to construct a
  42. B or C and return it to the caller as an A.  Because of the semantics, most
  43. likely D::getA() will have to create a temporary, so just returning a
  44. reference to some pre-existing B or C will not work.
  45.  
  46. Of course returning an A won't work because the pertinent information in
  47. either B or C is lost, and won't even compile because A is abstract.
  48.  
  49. The simple solution is to allocate the B or C off the heap, with the caller
  50. of D::getA() responsible for deleting it.  I don't like this solution
  51. because it is inelegant and the subclass of B or C is usually not kept
  52. around outside the scope of the caller.
  53.  
  54. The obvious solution is to use a class which can be Garbage Collected, but
  55. C++ currently has no such thing.
  56.  
  57. The best solution I could come up with is to create another class to handle
  58. managing a pointer to A such as the following.
  59.  
  60. class AHandler {
  61. private:
  62.     A* _a;
  63. public:
  64.     AHandler(A* a) { _a = a; a->ref(); }    // use reference counting GC
  65.     ~AHandler(A* a) { _a->unref(); }
  66.  
  67.     AHandler operator=(const AHandler &a) 
  68.     { a._a->ref(); _a->unref(); _a = a._a; }
  69.  
  70.     A* operator->() const { return _a; }
  71.     operator a&() const { return *_a; }
  72.     a& operator*() const { return *_a; }
  73. };
  74.  
  75. Then the member function getA() would return an AHandler, that it created
  76. using a B or C allocated off the heap.  Class A would implement reference
  77. counting (and probably a copy member that return an A*), and AHandler
  78. would take care of management of the A*.  The operators would allow AHandler
  79. to be treated like an A* or an A, depending on the context (in the actual
  80. implementation, A includes some overloaded operators for comparison, thus
  81. the operator a&() conversion).
  82.  
  83. My question is, I would like to be able to do this without having A handle
  84. reference counting.  Can anyone think of a good method?  Am I overlooking
  85. some simple, elegant solution?  Also, is this what is referred to as a
  86. "Smart pointer class?"
  87.  
  88. Thanks,
  89. -- 
  90. -----------------------------------------------------------------
  91. Lee D. Coller (coller@alnitak.usc.edu)        +1 (310) 379-0844
  92. USC Behavioral Technology Labs, 250 N. Harbor Dr. Ste 309
  93. Redondo Beach, California, 90277
  94.