C++ Constructors for converting length objects

Description

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;
}



PreviousNext

Related