首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在C++中编写具有多个数据字段的类似Java枚举的类?

如何在C++中编写具有多个数据字段的类似Java枚举的类?
EN

Stack Overflow用户
提问于 2009-12-27 13:20:45
回答 4查看 15.6K关注 0票数 62

我有Java背景,我发现C++的枚举非常差劲,我想知道如何在C++中编写类似Java的枚举(在枚举中枚举值是对象,可以有属性和方法)。

例如,将以下Java代码(其中的一部分,足以演示该技术)转换为C++:

代码语言:javascript
复制
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));
    }
}

任何帮助都将不胜感激!

谢谢!

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-12-27 14:17:23

模拟Java枚举的一种方法是创建一个具有私有构造函数的类,该构造函数将自身的副本实例化为静态变量:

代码语言:javascript
复制
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);  
// ... 

然后,您可以像这样使用枚举:

代码语言:javascript
复制
double gravityOnMercury = Planet::MERCURY.SurfaceGravity();
票数 77
EN

Stack Overflow用户

发布于 2015-04-13 05:42:24

随着C++11对constexpr的引入。还有另一种实现类型化枚举的方法。它的工作原理与普通枚举基本相同(存储为int变量,可以在switch语句中使用),但也允许它们具有成员函数。

在头文件中,您可以放入:

代码语言:javascript
复制
class Planet {
    int index;
public:
    static constexpr int length() {return 8;}
    Planet() : index(0) {}
    constexpr explicit Planet(int index) : index(index) {}
    constexpr operator int() const { return index; }

    double mass() const;
    double radius() const;

    double surfaceGravity() const;
};
constexpr Planet PLANET_MERCURY(0);
constexpr Planet PLANET_VENUS(1);
constexpr Planet PLANET_EARTH(2);
// etc.

在源文件中:

代码语言:javascript
复制
static double G = 6.67300E-11;

double Planet::mass() {
    switch(index) {
        case PLANET_MERCURY: return 3.303e+23;
        case PLANET_VENUS: return 4.869e+24;
        case PLANET_EARTH: return 5.976e+24;
        // Etc.
    }
}

double Planet::radius() {
    // Similar to mass.
}

double Planet::surfaceGravity() {
    return G * mass() / (radius() * radius());
}

然后可以将其用作:

代码语言:javascript
复制
double gravityOnMercury = PLANET_MERCURY.SurfaceGravity();

不幸的是,枚举条目不能定义为类主体中的静态常量。它们必须在声明时初始化,因为它们是constexpr,但在类内部,类还不是一个完整的类型,因此不能实例化。

票数 9
EN

Stack Overflow用户

发布于 2009-12-27 13:24:40

这是丑陋的、冗长的,而且通常是一种愚蠢的方式。但我想我应该发布一个完整的代码示例作为解释。对于额外的点,实际上可以通过稍微调整模板专门化来定义太阳系行星上的编译时扩展迭代。

代码语言:javascript
复制
#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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1965249

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档