C++ Constructors for converting length objects
#include <iostream> #include <iomanip> #include <memory> #include <string> #include <typeinfo> #include <vector> using std::string; class MyLength//from w w w .j a v a 2s . co m { protected: long mm {}; static double mmPerInch; static double mmPerMeter; static double inchesPerYard; static double yardsPerPerch; public: MyLength() = default; // Default constructor MyLength(long n) : mm(n) {} // Constructor from millimeters virtual double length() const { return mm; }; // Return the length virtual operator Inches()const;// Conversion to Inches virtual operator Yards()const; // Conversion to Yards virtual operator Meters()const;// Conversion to Meters virtual operator Perches()const;// Conversion to Perches }; class Inches : public MyLength { protected: double inches {}; public: Inches() = default; Inches(double ins) :MyLength {static_cast<long>(0.5 + mmPerInch*ins)}, inches {ins} {} double length() const override { return inches; } // Return the length // Inherited conversion to meters is OK operator Inches() const override { return *this; } operator Yards()const override; // Conversion to Yards operator Perches()const override; // Conversion to Perches // Constructors for conversions Inches(Meters& m); Inches(Yards& yds); Inches(Perches& p); }; class Meters: public MyLength { protected: double meters {}; public: Meters() = default; Meters(double m) : MyLength {static_cast<long>(0.5 + mmPerMeter*m)}, meters {m} {} double length() const override { return meters; } // Return the length // Constructors for conversions Meters(Inches& ins); Meters(Yards& yds); Meters(Perches& p); }; class Yards: public MyLength { protected: double yards {}; public: Yards() = default; Yards(double yds) :MyLength {static_cast<long>(0.5 + inchesPerYard*mmPerInch*yds)}, yards {yds} {} double length() const override { return yards; } // Return the length // Inherited conversion to meters is OK operator Yards() const override { return *this; } operator Perches()const override; // Conversion to Perches operator Inches()const override; // Conversion to Inches // Constructors for conversions Yards(Meters& m); Yards(Inches& ins); Yards(Perches& p); }; class Perches: public MyLength { protected: double perches {}; public: Perches():MyLength(){} Perches(double pch) :MyLength {static_cast<long>(0.5 + yardsPerPerch*inchesPerYard*mmPerInch*pch)}, perches {pch} {} double length() const override { return perches; }// Return the length operator Perches() const override { return *this; } operator Inches()const override; // Conversion to Perches operator Yards()const override; // Conversion to Yards // Constructors for conversions Perches(Meters& m); Perches(Inches& ins); Perches(Yards& yds); }; // Constructors for conversions inline Perches::Perches(Meters& m) : Perches {m.length()*mmPerMeter / (mmPerInch*inchesPerYard*yardsPerPerch)} { // std::cout << "Perches constructor from Meters" << std::endl; } inline Perches::Perches(Inches& ins) : Perches {ins.length() / (inchesPerYard*yardsPerPerch)} { // std::cout << "Perches constructor from Inches" << std::endl; } inline Perches::Perches(Yards& yds) : Perches {yds.length() / yardsPerPerch} { // std::cout << "Perches constructor from Yards" << std::endl; } inline Yards::Yards(Meters& m) : Yards {m.length()*mmPerMeter / (mmPerInch*inchesPerYard)} { // std::cout << "Yards constructor from Meters" << std::endl; } inline Yards::Yards(Inches& ins) : Yards {ins.length() / inchesPerYard} { std::cout << "Yards constructor from Inches" << std::endl; } inline Yards::Yards(Perches& p) : Yards {p.length()*yardsPerPerch} { // std::cout << "Yards constructor from Perches" << std::endl; } inline Meters::Meters(Inches& ins) : Meters {ins.length()*mmPerInch / mmPerMeter} { // std::cout << "Meters constructor from Inches" << std::endl; } inline Meters::Meters(Yards& yds) : Meters {yds.length()*inchesPerYard*mmPerInch / mmPerMeter} { // std::cout << "Meters constructor from Yards" << std::endl; } inline Meters::Meters(Perches& p) : Meters {p.length()*yardsPerPerch*inchesPerYard*mmPerInch / mmPerMeter} { // std::cout << "Meters constructor from Perches" << std::endl; } inline Inches::Inches(Meters& m) : Inches {m.length()*mmPerMeter / mmPerInch} { // std::cout << "Inches constructor from Meters" << std::endl; } inline Inches::Inches(Yards& yds) : Inches {yds.length()*inchesPerYard} { // std::cout << "Inches constructor from Yards" << std::endl; } inline Inches::Inches(Perches& p) : Inches {p.length()*yardsPerPerch*inchesPerYard} { // std::cout << "Inches constructor from Perches" << std::endl; } MyLength::operator Inches()const { return Inches {mm / mmPerInch}; } // Conversion to Inches MyLength::operator Yards()const { return Yards {mm / (mmPerInch*inchesPerYard)}; } // Conversion to Yards MyLength::operator Meters()const { return Meters {mm / mmPerMeter}; } // Conversion to Meters MyLength::operator Perches()const { return Perches {mm / (mmPerInch*inchesPerYard*yardsPerPerch)}; } // Conversion to Perches Inches::operator Yards()const { return Yards {inches / inchesPerYard}; } // Conversion to Yards Inches::operator Perches()const { return Perches {inches / (inchesPerYard*yardsPerPerch)}; } // Conversion to Perches Yards::operator Perches()const { return Perches {yards / yardsPerPerch}; } // Conversion to Perches Yards::operator Inches()const { return Inches {yards * inchesPerYard}; } // Conversion to Inches Perches::operator Inches()const { return Inches {perches * yardsPerPerch*inchesPerYard}; } // Conversion to Perches Perches::operator Yards()const { return Yards {perches * yardsPerPerch}; } // Conversion to Yards // Read a length from the keyboard std::shared_ptr<MyLength> readLength() { double value {}; // Stores the length value string units; // Stores the units for(;;) { std::cout << "\nEnter a length: "; std::cin >> std::skipws >> value; // Skip whitespace and read the value if (!value) return nullptr; getline(std::cin, units); // Rest of line is units int index {units.find_first_not_of(" ")}; // Find first non-blank in units // Return the object type corresponding to the units switch(toupper(units[index])) { case 'M': return std::make_shared<Meters>(value); case 'I': return std::make_shared<Inches>(value); case 'Y': return std::make_shared<Yards>(value);; case 'P': return std::make_shared<Perches>(value); default: std::cout << "\nInvalid units. Re-enter length: "; break; } } } class Inches; class Yards; class Meters; class Perches; // Initialize static data members double MyLength::mmPerInch {25.4}; double MyLength::mmPerMeter {1000.0}; double MyLength::inchesPerYard {36.0}; double MyLength::yardsPerPerch {5.5}; int main(){ std::vector<std::shared_ptr<MyLength> > pLengths; std::cout << "\nYou can enter lengths in inches, meters, yards, or perches." << "\nThe first character following the number specifies the units." << "\nThis can be i, m, y, or p, for inches, meters, yards, or perches." << "\ne.g. '22 ins' is 22 inches, '3.5 p' or '3.5perches' is 3.5 perches, '1y' is 1 yard." << std::endl << "\nPlease enter a length followed by the units or 0 to end:"; while (true) { auto p = readLength(); if (!p)break; pLengths.push_back(p); } for (auto p : pLengths) { std::cout << "\nLength is " << static_cast<Inches>(*p).length() << std::fixed << std::setprecision(2) << " inches, " << static_cast<Yards>(*p).length() << " yards, " << static_cast<Meters>(*p).length() << " meters, " << static_cast<Perches>(*p).length() << " perches, " << static_cast<long>(p->MyLength::length()) << " millimeters." << std::endl; } Inches inLength {5}; Yards ydLength {5}; Meters mLength {5}; Perches pchLength {5}; std::cout << "\nLength is " << inLength.length() << " inches, " << static_cast<Yards>(inLength).length() << " yards, " << static_cast<Meters>(inLength).length() << " meters, " << static_cast<Perches>(inLength).length() << " perches.\n"; std::cout << "Length is " << static_cast<Inches>(ydLength).length() << " inches, " << ydLength.length() << " yards, " << static_cast<Meters>(ydLength).length() << " meters, " << static_cast<Perches>(ydLength).length() << " perches,\n"; std::cout << "Length is " << static_cast<Inches>(mLength).length() << " inches, " << static_cast<Yards>(mLength).length() << " yards, " << mLength.length() << " meters, " << static_cast<Perches>(mLength).length() << " perches.\n"; std::cout << "Length is " << static_cast<Inches>(pchLength).length() << " inches, " << static_cast<Yards>(pchLength).length() << " yards, " << static_cast<Meters>(pchLength).length() << " meters, " << pchLength.length() << " perches. " << std::endl; }