C++ 如何创建一个只能添加到自身中一次的类?

C++ 如何创建一个只能添加到自身中一次的类?,c++,class,enums,operator-overloading,C++,Class,Enums,Operator Overloading,现在我有一个包含5个基值的枚举,我希望能够将5个基值中的任何一个相互组合,形成一个组合值,但我不希望将组合值添加到另一个基值 例如: enum class Color { Red, Green, Blue, White, Black } Color red = Color::Red; Color green = Color::Green; Color yellow = red + green; // Ok; yellow = Color::Yellow

现在我有一个包含5个基值的枚举,我希望能够将5个基值中的任何一个相互组合,形成一个组合值,但我不希望将组合值添加到另一个基值

例如:

enum class Color {
    Red,
    Green,
    Blue,
    White,
    Black
}

Color red = Color::Red;
Color green = Color::Green;
Color yellow = red + green; // Ok; yellow = Color::Yellow (Not sure how I would define this value)
Color orange = yellow + red; // Error; can't add to a combined value

// Note: It would be possible to add the same value to itself
// for example: Color::Red + Color::Red = Color::RedRed
我认为这可能必须更改为具有运算符重载的类,而不是枚举,但我不确定如何防止向另一个值添加组合值


这样做的优雅方式是什么?

首先,这需要运算符重载。然后,向类中添加一个私有bool。当您返回一个附加值时,bool被设置为true,表示它是先前添加的。 前


我认为不可能完全按照你的要求去做

我认为您需要两个独立的类
Color
PrimaryColor
。其中,
PrimaryColor
有一个重载的
运算符+
,允许您组合两个
PrimaryColor
并返回一个
Color

PrimaryColor
可以派生自
Color
,因此不需要组合它们的函数可以将它们视为一个整体

您可能希望保护构造函数,否则您的限制很容易被绕过

class PrimaryColor;

class Color {
  int r, g, b;
  explicit Color(int r, int g, int b) : r(r), g(g), b(b) {}
public:
  friend bool operator==(const Color& lhs, const Color& rhs) {
    return lhs.r == rhs.r && lhs.g == rhs.g && lhs.b == rhs.b;
  }

  static Color createYellow() { return Color{1, 1, 0}; }
  static Color createMagenta() { return Color{1, 0, 1}; }
  static Color createCyan() { return Color{0, 1, 1}; }    

  friend class PrimaryColor;    
  const static PrimaryColor Red;
  const static PrimaryColor Green;
  const static PrimaryColor Blue;
  const static Color Yellow;
  const static Color Magenta;
  const static Color Cyan;    
};

class PrimaryColor : public Color {
  explicit PrimaryColor(int r, int g, int b) : Color(r, g, b) {}    
public:
  Color operator+(const PrimaryColor& rhs) const {
    return Color(r+rhs.r, g+rhs.g, b+rhs.b);
  }

  static PrimaryColor createRed() { return PrimaryColor{1, 0, 0}; }
  static PrimaryColor createGreen() { return PrimaryColor{0, 1, 0}; }
  static PrimaryColor createBlue() { return PrimaryColor{0, 0, 1}; }
};

const PrimaryColor Color::Red = PrimaryColor::createRed();
const PrimaryColor Color::Green = PrimaryColor::createGreen();
const PrimaryColor Color::Blue = PrimaryColor::createBlue();

const Color Color::Yellow = Color::createYellow();
const Color Color::Magenta = Color::createMagenta();
const Color Color::Cyan = Color::createCyan();
通过在
Color
类中声明静态
PrimaryColor
Color
变量,您可以得到接近您要求的语法的东西:

void func(const Color& c1, const Color& c2);

int main() {
  auto red = Color::Red;
  auto green = Color::Green;
  auto yellow = red + green; // Ok
  assert(yellow == Color::Yellow);

  //auto orange = yellow + red; // Error; can't add to a combined value

  auto redred = Color::Red + Color::Red;

  func(red, yellow);  // Pass a PrimaryColor to a function taking a Color
}

编辑: 或者,您可以拥有
PrimaryColor
HybridColor
,这两种颜色都源自一个公共基类
Color

class PrimaryColor;
class HybridColor;

class Color {
protected:
  int r, g, b;
  explicit Color(int r, int g, int b) : r(r), g(g), b(b) {}
public:
  friend bool operator==(const Color& lhs, const Color& rhs) {
    return lhs.r == rhs.r && lhs.g == rhs.g && lhs.b == rhs.b;
  }  
  const static PrimaryColor Red;
  const static PrimaryColor Green;
  const static PrimaryColor Blue;
  const static HybridColor Yellow;
  const static HybridColor Magenta;
  const static HybridColor Cyan;    
};

class HybridColor : public Color {
  explicit HybridColor(int r, int g, int b) : Color(r, g, b) {}
public:   
  friend class PrimaryColor;
  static HybridColor createYellow() { return HybridColor{1, 1, 0}; }
  static HybridColor createMagenta() { return HybridColor{1, 0, 1}; }
  static HybridColor createCyan() { return HybridColor{0, 1, 1}; }  
};

class PrimaryColor : public Color {
  explicit PrimaryColor(int r, int g, int b) : Color(r, g, b) {}    
public:
  HybridColor operator+(const PrimaryColor& rhs) const {
    return HybridColor(r+rhs.r, g+rhs.g, b+rhs.b);
  }
  static PrimaryColor createRed() { return PrimaryColor{1, 0, 0}; }
  static PrimaryColor createGreen() { return PrimaryColor{0, 1, 0}; }
  static PrimaryColor createBlue() { return PrimaryColor{0, 0, 1}; }
};

const PrimaryColor Color::Red = PrimaryColor::createRed();
const PrimaryColor Color::Green = PrimaryColor::createGreen();
const PrimaryColor Color::Blue = PrimaryColor::createBlue();

const HybridColor Color::Yellow = HybridColor::createYellow();
const HybridColor Color::Magenta = HybridColor::createMagenta();
const HybridColor Color::Cyan = HybridColor::createCyan();

.

我认为没有办法做到这一点。如果它返回相同的类,则可以对其使用其所有运算符。您需要使加法运算符返回一个不同的类。您不需要将其更改为类,只需将运算符放在命名空间范围内即可。这对我来说根本没有意义。为什么值上的运算符取决于如何获得值
Color blue=Color::blue
——您可以添加到其中。但是
Color blue=Color::Red+Color::Green
——您不能添加到它。即使它在
blue
变量中的值相同。您希望在编译时还是在运行时出错?这就像说您希望
x=5
x=2+3
之间存在差异一样。谢谢,第二个示例与我想要的非常接近。
class PrimaryColor;
class HybridColor;

class Color {
protected:
  int r, g, b;
  explicit Color(int r, int g, int b) : r(r), g(g), b(b) {}
public:
  friend bool operator==(const Color& lhs, const Color& rhs) {
    return lhs.r == rhs.r && lhs.g == rhs.g && lhs.b == rhs.b;
  }  
  const static PrimaryColor Red;
  const static PrimaryColor Green;
  const static PrimaryColor Blue;
  const static HybridColor Yellow;
  const static HybridColor Magenta;
  const static HybridColor Cyan;    
};

class HybridColor : public Color {
  explicit HybridColor(int r, int g, int b) : Color(r, g, b) {}
public:   
  friend class PrimaryColor;
  static HybridColor createYellow() { return HybridColor{1, 1, 0}; }
  static HybridColor createMagenta() { return HybridColor{1, 0, 1}; }
  static HybridColor createCyan() { return HybridColor{0, 1, 1}; }  
};

class PrimaryColor : public Color {
  explicit PrimaryColor(int r, int g, int b) : Color(r, g, b) {}    
public:
  HybridColor operator+(const PrimaryColor& rhs) const {
    return HybridColor(r+rhs.r, g+rhs.g, b+rhs.b);
  }
  static PrimaryColor createRed() { return PrimaryColor{1, 0, 0}; }
  static PrimaryColor createGreen() { return PrimaryColor{0, 1, 0}; }
  static PrimaryColor createBlue() { return PrimaryColor{0, 0, 1}; }
};

const PrimaryColor Color::Red = PrimaryColor::createRed();
const PrimaryColor Color::Green = PrimaryColor::createGreen();
const PrimaryColor Color::Blue = PrimaryColor::createBlue();

const HybridColor Color::Yellow = HybridColor::createYellow();
const HybridColor Color::Magenta = HybridColor::createMagenta();
const HybridColor Color::Cyan = HybridColor::createCyan();