Как записать Java-enum-like класс с несколькими полями данных в C++?

Происходя из среды Java, я нахожу перечисления C++ очень хромыми. Я хотел знать, как записать подобные Java перечисления (те, в которых перечислимые значения являются объектами и могут иметь атрибуты и методы) в C++.

Например, переведите следующий код Java (часть его, достаточный для демонстрации техники) C++:

public enum Planet {
    MERCURY (3.303e+23, 2.4397e6),
    VENUS   (4.869e+24, 6.0518e6),
    EARTH   (5.976e+24, 6.37814e6),
    MARS    (6.421e+23, 3.3972e6),
    JUPITER (1.9e+27,   7.1492e7),
    SATURN  (5.688e+26, 6.0268e7),
    URANUS  (8.686e+25, 2.5559e7),
    NEPTUNE (1.024e+26, 2.4746e7);

    private final double mass;   // in kilograms
    private final double radius; // in meters
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }
    private double mass()   { return mass; }
    private double radius() { return radius; }

    // universal gravitational constant  (m3 kg-1 s-2)
    public static final double G = 6.67300E-11;

    double surfaceGravity() {
        return G * mass / (radius * radius);
    }
    double surfaceWeight(double otherMass) {
        return otherMass * surfaceGravity();
    }
    public static void main(String[] args) {
        if (args.length != 1) {
            System.err.println("Usage:  java Planet <earth_weight>");
            System.exit(-1);
        }
        double earthWeight = Double.parseDouble(args[0]);
        double mass = earthWeight/EARTH.surfaceGravity();
        for (Planet p : Planet.values())
           System.out.printf("Your weight on %s is %f%n",
                             p, p.surfaceWeight(mass));
    }
}

Любая справка значительно ценилась бы!

Спасибо!

53
задан einpoklum - reinstate Monica 5 January 2014 в 21:16
поделиться

3 ответа

Один из способов моделирования Java-перечислений - это создание класса с частным конструктором, который инстанцирует копии себя в виде статических переменных:

class Planet {  
  public: 
    // Enum value DECLARATIONS - they are defined later 
    static const Planet MERCURY;  
    static const Planet VENUS;  
    // ... 

  private: 
    double mass;   // in kilograms  
    double radius; // in meters  

  private: 
    Planet(double mass, double radius) {  
        this->mass = mass;  
        this->radius = radius;  
    } 

  public: 
    // Properties and methods go here 
}; 

// Enum value DEFINITIONS 
// The initialization occurs in the scope of the class,  
// so the private Planet constructor can be used. 
const Planet Planet::MERCURY = Planet(3.303e+23, 2.4397e6);  
const Planet Planet::VENUS = Planet(4.869e+24, 6.0518e6);  
// ... 

Затем можно использовать перечисления следующим образом:

double gravityOnMercury = Planet::MERCURY.SurfaceGravity();
71
ответ дан 7 November 2019 в 08:46
поделиться

Может быть, это то, что вам нужно --

#include<iostream>

using namespace std;

class Planet {
    double mass,radius;

    Planet(double m, double r) : mass(m) : radius(r) {}

public:
    static const Planet MERCURY;

    void show(){
        cout<<mass<<","<<radius<<endl;
    }
} ;
const Planet Planet::MERCURY = Planet(1.0,1.2);

int main(){
    Planet p = Planet::MERCURY;
    p.show();
}

Это всего лишь небольшой код, я уверен, что вы можете модифицировать его под свои нужды...

1
ответ дан 7 November 2019 в 08:46
поделиться

Это уродливый, многословный, и вообще тупой способ. Но я решил поместить полный пример кода в качестве объяснения. Для дополнительных моментов на самом деле можно определить расширенную по времени компиляции итерацию по солнечным планетам, откорректировав специализацию шаблонов немного.

#include <string>
#include <sstream>
#include <iostream>
#include <cstdlib>

class Planet {
 public:
   static const double G = 6.67300E-11;

   Planet(const ::std::string &name, double mass, double radius)
        : name_(name), mass_(mass), radius_(radius)
      {}
   const ::std::string &name() const { return name_; }
   double surfaceGravity() const {
      return G * mass_ / (radius_ * radius_);
   }
   double surfaceWeight(double otherMass) const {
      return otherMass * surfaceGravity();
   }

 private:
   const ::std::string name_;
   const double mass_;
   const double radius_;
};

enum SolarPlanets {
   MERCURY,
   VENUS,
   EARTH,
   MARS,
   JUPITER,
   SATURN,
   URANUS,
   NEPTUNE
};

template <SolarPlanets planet>
class SolarPlanet : public Planet {
};

template <>
class SolarPlanet<MERCURY> : public Planet {
 public:
   SolarPlanet() : Planet("MERCURY", 3.303e+23, 2.4397e6) {}
};

template <>
class SolarPlanet<VENUS> : public Planet {
 public:
   SolarPlanet() : Planet("VENUS", 4.869e+24, 6.0518e6) {}
};

template <>
class SolarPlanet<EARTH> : public Planet {
 public:
   SolarPlanet() : Planet("EARTH", 5.976e+24, 6.37814e6) {}
};

template <>
class SolarPlanet<MARS> : public Planet {
 public:
   SolarPlanet() : Planet("MARS", 6.421e+23, 3.3972e6) {}
};

template <>
class SolarPlanet<JUPITER> : public Planet {
 public:
   SolarPlanet() : Planet("JUPITER", 1.9e+27, 7.1492e7 ) {}
};

template <>
class SolarPlanet<SATURN> : public Planet {
 public:
   SolarPlanet() : Planet("SATURN", 5.688e+26, 6.0268e7) {}
};

template <>
class SolarPlanet<URANUS> : public Planet {
 public:
   SolarPlanet() : Planet("URANUS", 8.686e+25, 2.5559e7) {}
};

template <>
class SolarPlanet<NEPTUNE> : public Planet {
 public:
   SolarPlanet() : Planet("NEPTUNE", 1.024e+26, 2.4746e7) {}
};

void printTerranWeightOnPlanet(
   ::std::ostream &os, double terran_mass, const Planet &p
   )
{
   const double mass = terran_mass / SolarPlanet<EARTH>().surfaceGravity();
   os << "Your weight on " << p.name() << " is " << p.surfaceWeight(mass) << '\n';
}

int main(int argc, const char *argv[])
{
   if (argc != 2) {
      ::std::cerr << "Usage: " << argv[0] << " <earth_weight>\n";
      return 1;
   }
   const double earthweight = ::std::atof(argv[1]);
   printTerranWeightOnPlanet(::std::cout, earthweight, SolarPlanet<MERCURY>());
   printTerranWeightOnPlanet(::std::cout, earthweight, SolarPlanet<VENUS>());
   printTerranWeightOnPlanet(::std::cout, earthweight, SolarPlanet<EARTH>());
   printTerranWeightOnPlanet(::std::cout, earthweight, SolarPlanet<MARS>());
   printTerranWeightOnPlanet(::std::cout, earthweight, SolarPlanet<JUPITER>());
   printTerranWeightOnPlanet(::std::cout, earthweight, SolarPlanet<SATURN>());
   printTerranWeightOnPlanet(::std::cout, earthweight, SolarPlanet<URANUS>());
   printTerranWeightOnPlanet(::std::cout, earthweight, SolarPlanet<NEPTUNE>());
   return 0;
}
1
ответ дан 7 November 2019 в 08:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: