C++ Class Definition Creating length objects

Description

C++ Class Definition Creating length objects

#include <iostream>
#include <iomanip>
#include <memory>
#include <string>
#include <typeinfo>
#include <vector>
using std::string;

class MyLength/*from ww w  .j  ava2  s.  com*/
{
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
};

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

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

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

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

// Initialize static data members
double MyLength::mmPerInch {25.4};
double MyLength::mmPerMeter {1000.0};
double MyLength::inchesPerYard {36.0};
double MyLength::yardsPerPerch {5.5};

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

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

  }

  // Output the lengths - we must figure out what type they are to display the units
  for(auto p : pLengths)
  {
    string units(" invalid type");
    if(typeid(*p)==typeid(Inches))
      units = " inches";
    else if(typeid(*p)==typeid(Meters))
      units = " meters";
    else if(typeid(*p)==typeid(Yards))
      units = " yards";
    else if(typeid(*p)==typeid(Perches))
      units = " perches";
    std::cout << "\nLength is " << std::fixed << std::setprecision(2) << p->length() << units
              << " which is "   << static_cast<long>(p->MyLength::length()) << " millimeters." << std::endl;
  }
}



PreviousNext

Related