home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / IDIOMS.ZIP / 5NMAROW.C < prev    next >
C/C++ Source or Header  |  1991-12-04  |  4KB  |  169 lines

  1. /* Copyright (c) 1992 by AT&T Bell Laboratories. */
  2. /* Advanced C++ Programming Styles and Idioms */
  3. /* James O. Coplien */
  4. /* All rights reserved. */
  5.  
  6. #include <iostream.h>
  7. #include <stdio.h>
  8.  
  9. struct BaseConstructor { BaseConstructor(int) { } };
  10.  
  11. class NumberRep;
  12.  
  13. class Number {
  14. public:
  15.     Number(BaseConstructor);
  16.     Number();
  17.     Number(double d);
  18.     Number(double rpart, double ipart);
  19.     Number operator=(Number &);
  20.     void redefine(NumberRep *);
  21.     Number(Number &);
  22.     NumberRep *operator->();
  23. private:
  24.     NumberRep *rep;
  25. };
  26.  
  27. class NumberRep {
  28. public:
  29.     virtual Number operator+(Number &);
  30.     virtual Number complexAdd(NumberRep &);
  31.     virtual Number doubleAdd(NumberRep &);
  32.     virtual ostream &operator<<(ostream &o) { return o; }
  33.     NumberRep(): referenceCount(0) { }
  34.     short referenceCount;
  35. };
  36.  
  37. Number
  38. NumberRep::operator+(Number &) { static Number n;  return n; }
  39.  
  40. Number
  41. NumberRep::complexAdd(NumberRep &) { static Number n; return n; }
  42.  
  43. Number
  44. NumberRep::doubleAdd(NumberRep &) { static Number n; return n; }
  45.  
  46. NumberRep *
  47. Number::operator->() { return rep; }
  48.  
  49. Number
  50. Number::operator=(Number & n) {
  51.         n.rep->referenceCount++;
  52.         if (--rep->referenceCount == 0) delete rep;
  53.         rep = n.rep;
  54.         return *this;
  55. }
  56. void
  57. Number::redefine(NumberRep *n) {
  58.         if (--rep->referenceCount == 0) delete rep;
  59.         rep = n;
  60. }
  61. Number::Number(Number & n) {
  62.         n.rep->referenceCount++;
  63.         rep = n.rep;
  64. }
  65.  
  66. class Complex: public NumberRep {
  67. friend class RealNumber;
  68. public:
  69.     Complex(double d, double e): NumberRep() {
  70.         rpart = d; ipart = e;
  71.         referenceCount = 1;
  72.     }
  73.     Number operator+(Number &num) {
  74.         Number n = num->complexAdd(*this);
  75.         return n;
  76.     }
  77.     Number complexAdd(NumberRep &n);
  78.     Number doubleAdd(NumberRep &n);
  79.     ostream& operator<<(ostream& o) {
  80.         o << "Complex(" << rpart << "," << ipart << ")";
  81.         return o;
  82.     }
  83. private:
  84.     double rpart, ipart;
  85. };
  86.  
  87. class RealNumber: public NumberRep {
  88. friend Complex;
  89. public:
  90.     RealNumber(double d): NumberRep() {
  91.         r = d;
  92.         referenceCount = 1;
  93.     }
  94.     Number operator+(Number &num) {
  95.         Number newnum = num->doubleAdd(*this);
  96.         return newnum;
  97.     }
  98.     Number complexAdd(NumberRep &n);
  99.     Number doubleAdd(NumberRep &n) {
  100.         Number retval;
  101.         RealNumber *c1 = new RealNumber(*this);
  102.         RealNumber *c2 = (RealNumber*)&n;
  103.         c1->r += c2->r;
  104.         retval.redefine(c1);
  105.         return retval;
  106.     }
  107.     ostream& operator<<(ostream& o) {
  108.         o << "Float(" << r << ")";
  109.         return o;
  110.     }
  111. private:
  112.     double r;
  113. };
  114.  
  115. ostream& operator<<(ostream&o, Number &n) {
  116.     return n->operator<<(o);
  117. }
  118.  
  119. Number::Number(BaseConstructor) {
  120. }
  121.  
  122. Number::Number() {
  123.     rep = new RealNumber(0.0);
  124. }
  125.  
  126. Number::Number(double d) {
  127.     rep = new RealNumber(d);
  128. }
  129.  
  130. Number::Number(double d, double e) {
  131.     rep = new Complex(d, e);
  132. }
  133.  
  134. Number Complex::complexAdd(NumberRep &n) {
  135.     Number retval;
  136.     Complex *c1 = new Complex(*this);
  137.     Complex *c2 = (Complex*)&n;
  138.     c1->rpart += c2->rpart;
  139.     c1->ipart += c2->ipart;
  140.     retval.redefine(c1);
  141.     return retval;
  142. }
  143.  
  144. Number Complex::doubleAdd(NumberRep &n) {
  145.     Number retval;
  146.     Complex *c1 = new Complex(*this);
  147.     RealNumber *c2 = (RealNumber*)&n;
  148.     c1->rpart += c2->r;
  149.     retval.redefine(c1);
  150.     return retval;
  151. }
  152.  
  153. Number RealNumber::complexAdd(NumberRep &n) {
  154.     Number retval;
  155.     Complex *c1 = new Complex(r, 0);
  156.     Complex *c2 = (Complex*)&n;
  157.     c1->rpart += c2->rpart;
  158.     c1->ipart += c2->ipart;
  159.     retval.redefine(c1);
  160.     return retval;
  161. }
  162.  
  163. int main() {
  164.     Number a = Number(1.0, 1.0);
  165.     Number b = 2.0;
  166.     Number c = a->operator+(b);
  167.     cout << "a = " << a << ", b = " << b << ", c = " << c << "\n";
  168. }
  169.