/* Copyright (c) 1992 by AT&T Bell Laboratories. */ /* Advanced C++ Programming Styles and Idioms */ /* James O. Coplien */ /* All rights reserved. */ #include #include struct BaseConstructor { BaseConstructor(int=0) { } }; class Number { public: Number(BaseConstructor); Number(); Number(double d); Number(double rpart, double ipart); Number operator=(Number & n) { printf("Number::operator=(Number&)\n"); n.rep->referenceCount++; if (--rep->referenceCount == 0) delete rep; rep = n.rep; return *this; } void redefine(Number *n) { printf("Number::redefine(Number*)\n"); if (--rep->referenceCount == 0) delete rep; rep = n; } Number(Number & n) { printf("Number::Number(Number&)\n"); n.rep->referenceCount++; rep = n.rep; referenceCount = 1; } virtual ostream& operator<<(ostream &s) { printf("Number::operator<<(ostream&)\n"); return rep->operator<<(s); } virtual Number operator+(Number &n) { printf("Number::operator+(Number&)\n"); return rep->operator+(n); } virtual Number complexAdd(Number &n) { printf("Number::complexAdd(Number&)\n"); return rep->complexAdd(n); } virtual Number doubleAdd(Number &n) { printf("Number::doubleAdd(Number&)\n"); return rep->doubleAdd(n); } private: Number *rep; short referenceCount; }; class Complex: public Number { friend class RealNumber; public: Complex(double d, double e): Number(BaseConstructor()) { printf("Complex::Complex(double, double)\n"); rpart = d; ipart = e; } Complex(const Complex& c): rpart(c.rpart), ipart(c.ipart), Number(BaseConstructor()) { } Number operator+(Number &num) { printf("Complex::operator+(Number&)\n"); Number n = num.complexAdd(*this); return n; } Number complexAdd(Number &n); Number doubleAdd(Number &n); ostream& operator<<(ostream& o) { o << "Complex(" << rpart << "," << ipart << ")"; return o; } private: double rpart, ipart; }; class RealNumber: public Number { friend Complex; public: RealNumber(double d): Number(BaseConstructor()) { printf("RealNumber::RealNumber(double)\n"); r = d; } RealNumber(const RealNumber& n): r(n.r), Number(BaseConstructor()) { } /******/ Number operator+(Number &num) { printf("RealNumber::operator+(Number&)\n"); Number newnum = num.doubleAdd(*this); return newnum; } Number complexAdd(Number &n); Number doubleAdd(Number &n) { printf("RealNumber::doubleAdd(Number&)\n"); Number retval; RealNumber *c1 = new RealNumber(*this); RealNumber *c2 = (RealNumber*)&n; c1->r += c2->r; retval.redefine(c1); return retval; } ostream& operator<<(ostream& o) { printf("RealNumber::operator<<(ostream&)\n"); o << "Float(" << r << ")"; return o; } private: double r; }; ostream& operator<<(ostream&o, Number n) { Number *np = &n; return np->operator<<(o); } Number::Number(BaseConstructor) { printf("Number::Number(BaseConstructor)\n"); referenceCount = 1; } Number::Number() { printf("Number::Number()\n"); rep = new RealNumber(0.0); referenceCount = 1; } Number::Number(double d) { printf("Number::Number(double)\n"); rep = new RealNumber(d); referenceCount = 1; } Number::Number(double d, double e) { printf("Number::Number(double,double)\n"); rep = new Complex(d, e); referenceCount = 1; } Number Complex::complexAdd(Number &n) { printf("Number::complexAdd(Number&)\n"); Number retval; Complex *c1 = new Complex(*this); Complex *c2 = (Complex*)&n; c1->rpart += c2->rpart; c1->ipart += c2->ipart; retval.redefine(c1); return retval; } Number Complex::doubleAdd(Number &n) { printf("Complex::doubleAdd(Number&)\n"); Number retval; Complex *c1 = new Complex(*this); RealNumber *c2 = (RealNumber*)&n; c1->rpart += c2->r; retval.redefine(c1); return retval; } Number RealNumber::complexAdd(Number &n) { printf("RealNumber::complexAdd(Number&)\n"); Number retval; Complex *c1 = new Complex(r, 0); Complex *c2 = (Complex*)&n; c1->rpart += c2->rpart; c1->ipart += c2->ipart; retval.redefine(c1); return retval; } int main() { Number a = Number(1.0, 1.0); Number b = 2.0; Number c = a + b; Number d = c + a; // added this one line and example bombs cout << "a = " << a << ", b = " << b << ", c = " << c << "\n"; }