如何创建只能添加一次的 class?
How can I create a class that can be added to itself only once?
现在我有一个包含 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
我认为这可能必须更改为具有运算符重载的 class 而不是枚举,但我不确定如何防止将组合值添加到另一个值。
这样做的优雅方式是什么?
首先,这需要运算符重载。然后,您向 class 添加一个私有布尔值。当您 return 添加一个值时,布尔值设置为 true,表示它之前已添加。
例如
class oneAdd
{
private:
bool hasAdded;
public:
int member;
void setAdded() { hasAdded = true; }
oneAdd operator+(const oneAdd& toAdd)
{
if (!hasAdded) {
oneAdd ret;
ret.member = member + toAdd.member;
ret.setAdded();
return ret;
} else {
// Throw some error. This operator shouldn't have been called.
}
}
};
我认为不可能完全按照您的要求去做。
我认为您需要两个单独的 classes Color
和 PrimaryColor
。其中 PrimaryColor
有一个重载的 operator+
允许您组合两个 PrimaryColor
和 return 一个 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
class 中声明静态 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
,它们都派生自一个共同的基础 class 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();
现在我有一个包含 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
我认为这可能必须更改为具有运算符重载的 class 而不是枚举,但我不确定如何防止将组合值添加到另一个值。
这样做的优雅方式是什么?
首先,这需要运算符重载。然后,您向 class 添加一个私有布尔值。当您 return 添加一个值时,布尔值设置为 true,表示它之前已添加。 例如
class oneAdd
{
private:
bool hasAdded;
public:
int member;
void setAdded() { hasAdded = true; }
oneAdd operator+(const oneAdd& toAdd)
{
if (!hasAdded) {
oneAdd ret;
ret.member = member + toAdd.member;
ret.setAdded();
return ret;
} else {
// Throw some error. This operator shouldn't have been called.
}
}
};
我认为不可能完全按照您的要求去做。
我认为您需要两个单独的 classes Color
和 PrimaryColor
。其中 PrimaryColor
有一个重载的 operator+
允许您组合两个 PrimaryColor
和 return 一个 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
class 中声明静态 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
,它们都派生自一个共同的基础 class 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();