jamesh@cs.umr.edu (James Hartley) (11/28/90)
I recently tried taking advantage of virtual functions by creating a generic routine which would take a base class pointer and output the appropriate derived class where the insertor was properly overloaded. The following program attempts to illustrate the idea. Turbo C++ balks at the output statement in main() because the insertor is not defined with respect to the base class. Is this operator resolution beyond the restraints of the language, or is this a bug in the compiler? ----------------------- BEGIN CODE ------------------------------------- #include <iostream.h> const float pi = 3.14159; class figure { // abstract base class definition protected: float r, h; public: virtual float volume(void) = 0; }; class sphere : public figure { // derived class definition public: sphere(float radius) { r = radius; } virtual float volume(void) { return 4.0 / 3.0 * pi * r * r * r; } friend ostream &operator<<(ostream&, sphere&); }; ostream &operator<<(ostream &strm, sphere &sph) { strm << "VOLUME OF SPHERE:\n"; strm << "radius = " << sph.r << "\n"; strm << "volume = " << sph.volume() << "\n"; return strm; } main() { figure *fig = new sphere(2.0); cout << *fig << "\n"; return 0; } ------------------------- END CODE ------------------------------------- -- James J. Hartley Internet: jamesh@cs.umr.edu Department of Computer Science Bitnet: jamesh@cs.umr.edu@umrvmb.bitnet University of Missouri - Rolla UUCP: ...!uunet!cs.umr.edu!jamesh
fuchs@it.uka.de (Harald Fuchs) (11/30/90)
jamesh@cs.umr.edu (James Hartley) writes: >I recently tried taking advantage of virtual functions by creating a generic >routine which would take a base class pointer and output the appropriate >derived class where the insertor was properly overloaded. The following >program attempts to illustrate the idea. Turbo C++ balks at the output >statement in main() because the insertor is not defined with respect to >the base class. Is this operator resolution beyond the restraints of the >language, or is this a bug in the compiler? You get the inserter you want by making it virtual. You can't do this directly because the standard insertion operator<< expects your "figure" to be the 2nd argument. Do it like that: class figure { // abstract base class definition protected: float r, h; public: virtual float volume(void) = 0; virtual void printOn (ostream&) const = 0; }; inline ostream& operator<< (ostream& s, const figure& x) { x.printOn (s); return s; } class sphere : public figure { // derived class definition public: sphere(float radius) { r = radius; } virtual float volume(void) { return 4.0 / 3.0 * pi * r * r * r; } void printOn (ostream&) const; }; void sphere::printOn (ostream& strm) const { strm << "VOLUME OF SPHERE:\n"; strm << "radius = " << sph.r << "\n"; strm << "volume = " << sph.volume() << "\n"; } main() { figure *fig = new sphere (2.0); cout << *fig << "\n"; return 0; } -- Harald Fuchs <fuchs@it.uka.de> <fuchs%it.uka.de@relay.cs.net> ... <fuchs@telematik.informatik.uni-karlsruhe.dbp.de> *gulp*
rmartin@clear.com (Bob Martin) (11/30/90)
In article <1747@umriscc.isc.umr.edu> jamesh@cs.umr.edu (James Hartley) writes: >I recently tried taking advantage of virtual functions by creating a generic >routine which would take a base class pointer and output the appropriate >derived class where the insertor was properly overloaded. The following >program attempts to illustrate the idea. Turbo C++ balks at the output >statement in main() because the insertor is not defined with respect to >the base class. Is this operator resolution beyond the restraints of the >language, or is this a bug in the compiler? > >----------------------- BEGIN CODE ------------------------------------- > >#include <iostream.h> > >const float pi = 3.14159; > >class figure { // abstract base class definition >protected: > float r, h; >public: > virtual float volume(void) = 0; >}; > >class sphere : public figure { // derived class definition >public: > sphere(float radius) { r = radius; } > virtual float volume(void) { return 4.0 / 3.0 * pi * r * r * r; } > friend ostream &operator<<(ostream&, sphere&); >}; > >ostream &operator<<(ostream &strm, sphere &sph) { > strm << "VOLUME OF SPHERE:\n"; > strm << "radius = " << sph.r << "\n"; > strm << "volume = " << sph.volume() << "\n"; > return strm; >} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This function defines the << operator for a sphere but not for a figure. > >main() { > figure *fig = new sphere(2.0); > cout << *fig << "\n"; ^^^^^^^^^^^^^^^^^^^^^^^^^^ The compiler cannot resolve this statement because there is not << operator defined for a figure. > return 0; >} > >------------------------- END CODE ------------------------------------- > >-- >James J. Hartley Internet: jamesh@cs.umr.edu >Department of Computer Science Bitnet: jamesh@cs.umr.edu@umrvmb.bitnet >University of Missouri - Rolla UUCP: ...!uunet!cs.umr.edu!jamesh What you need to do is declare a virtual function (say printOn) for sphere. Then in operator<<(ostream&, figure&) call the virtual function. -- +-Robert C. Martin-----+:RRR:::CCC:M:::::M:| Nobody is responsible for | | rmartin@clear.com |:R::R:C::::M:M:M:M:| my words but me. I want | | uunet!clrcom!rmartin |:RRR::C::::M::M::M:| all the credit, and all | +----------------------+:R::R::CCC:M:::::M:| the blame. So there. |
jimad@microsoft.UUCP (Jim ADCOCK) (12/06/90)
Issues of overloading are probably too complicated to do justice here. I refer you to pages 307 to 339 of "The Annotated C++ Reference Manual." Consider instead the approach below -- the standard trick of introducing an intermediate helper function to allow polymorphism on a second parameter. const float pi = 3.14159; class figure { // abstract base class definition protected: float r, h; public: virtual float volume(void) = 0; friend ostream& operator<< (ostream& s, figure& self) { return self.shiftout(s); } virtual ostream& shiftout(ostream&) = 0; }; class sphere : public figure { // derived class definition public: sphere(float radius) { r = radius; } virtual float volume(void) { return 4.0 / 3.0 * pi * r * r * r; } virtual ostream& shiftout(ostream&); }; ostream& sphere::shiftout (ostream &strm) { strm << "VOLUME OF SPHERE:\n"; strm << "radius = " << r << "\n"; strm << "volume = " << volume() << "\n"; return strm; } main() { figure *fig = new sphere(2.0); cout << *fig << "\n"; return 0; }