C++ 颜色的类层次结构

C++ 颜色的类层次结构,c++,class,colors,hierarchy,C++,Class,Colors,Hierarchy,我在确定用于存储RGB/RGBA颜色信息的类结构时遇到问题 我正在制作一个非常简单的3D游戏引擎,以获得乐趣并磨练我的OO编程能力 我希望我的引擎能够同时支持RGB和RGBA颜色。最重要的是,我希望使用它,以便可以将RGB和RGBA值指定为固定到[0,1]的浮点或无符号字符。我认为出于存储目的,最好使用无符号字符,因为它们使用的内存是浮点的四分之一 现在,我设计了以下用于此的类:Color、Color3、Color3f、Color3c、Color4、Color4f和Color4c。Color是C

我在确定用于存储RGB/RGBA颜色信息的类结构时遇到问题

我正在制作一个非常简单的3D游戏引擎,以获得乐趣并磨练我的OO编程能力

我希望我的引擎能够同时支持RGB和RGBA颜色。最重要的是,我希望使用它,以便可以将RGB和RGBA值指定为固定到[0,1]的浮点或无符号字符。我认为出于存储目的,最好使用无符号字符,因为它们使用的内存是浮点的四分之一

现在,我设计了以下用于此的类:Color、Color3、Color3f、Color3c、Color4、Color4f和Color4c。Color是Color3和Color4的超类,而Color3是Color3f和Color3c的超类,正如Color4与Color4f和Color4c一样

这似乎是一种比实际需要复杂得多的方法。我也考虑过使用泛型,所以不用Color3f和Color3c,而是使用Color3和Color3。然而,这种方法似乎也不正确

理想情况下,我希望能够编写如下代码:

color3red1(255,0,0);
颜色3红色2(1.0f、0.0f、0.0f);
颜色*someColor=新颜色3(1.0f、0.0f、0.5f);
颜色4另一种颜色=*someColor;
Color4 thisColor=anotherColor.toChar();
//thisColor.r=255,thisColor.g=0,thisColor.b=127
thisColor=thisColor.toFloat();
//thisColor.r=1.0f,thisColor.g=0.0f,thisColor.b=0.5f
<>这在C++中是不能实现的(至少我的知识),但是如何在不创建7个单独的类的情况下收集相同的功能?而且不存储浪费的信息?例如,在内存中绘制1024x1024图像。这将是一个包含超过一百万种颜色的数组,那么我如何创建一个灵活且可重用的颜色类层次结构呢?i、 例如,通过无符号字符在不同的结构中存储RGB和RGBA值,但是否提供检索浮点值的功能


对不起,如果这不够具体,这是我的第一个问题!让我知道还有什么会有帮助。如果你们愿意的话,我可以发布我迄今为止尝试过的代码,但希望你们能理解我试图实现的目标。

你们只需要一种类颜色(或最好的颜色)

在内部,您可以随意存储值,32位无符号整数RGBA(或BGRA)很常见,然后只需使用掩码和位移位来提取每个组件

您可以让构造函数采用
颜色(无符号字符红色、无符号字符绿色、无符号字符蓝色、无符号字符alpha=0xff)
或浮动

和类似的getter/setter,用于每个表单中的每个组件


编辑:但是,如果你正在计划任何一种高性能的图像,由每个像素的颜色对象数组组成的图像可能是不可取的。您可能需要查看一组静态函数来设置/获取每个组件和一个构造函数,该构造函数采用图像格式的像素(即BGRA或RGB unsigned int)

Xeo关于过度工程的观点是一个很好的观点,您可能需要阅读我关于避免的回答。但OO的全部目的是隐藏复杂性,而不是鼓励复杂性


从一个具有一些有效内部表示的Color类开始,并为您想要作为参数的数据类型重载构造函数。除非您需要公开实现,否则不必担心所有的子类。采取可能有效的最简单方法。

这只是对其他人所说的内容进行编码,因为它看起来很有趣。这不是答案

class color {
    unsigned char red_, green_, blue_, alpha_;
public:
    color() 
    :red_(0), green_(0), blue_(0), alpha_(0xFF) {}
    color(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha=0xFF)
    :red_(red), green_(green), blue_(blue), alpha_(alpha) {}
    color(float red, float green, float blue, float alpha=1.0)
    :red_(red*255.0+.5), green_(green*255.0+.5), blue_(blue*255.0+.5), alpha_(alpha*255.0+.5) {}
    color(const color& rhs)
    :red_(rhs.red_), green_(rhs.green_), blue_(rhs.blue_), alpha_(rhs.alpha_) {}
    //operator= and dtor automatically generated
    unsigned char& c_red() {return red_;}
    unsigned char& c_green() {return green_;}
    unsigned char& c_blue() {return blue_;}
    unsigned char& c_alpha() {return alpha_;}
    const unsigned char& c_red() const {return red_;}
    const unsigned char& c_green() const {return green_;}
    const unsigned char& c_blue() const {return blue_;}
    const unsigned char& c_alpha() const {return alpha_;}
    void set_f_red(float val) {red_=val*255.0+.5;}
    void set_f_green(float val) {green_=val*255.0+.5;}
    void set_f_blue(float val) {blue_=val*255.0+.5;}
    void set_f_alpha(float val) {alpha_=val*255.0+.5;}
    float get_f_red() const {return red_/255.0;}
    float get_f_green() const {return green_/255.0;}
    float get_f_blue() const {return blue_/255.0;}
    float get_f_alpha() const {return alpha_/255.0;}

    unsigned int rgba() {return (red_<<24)|(green_<<16)|(blue_<<8)|(alpha_<<0);}
};
类颜色{
无符号字符红、绿、蓝、阿尔法;
公众:
颜色()
:红色(0)、绿色(0)、蓝色(0)、阿尔法(0xFF){}
颜色(无符号字符红色、无符号字符绿色、无符号字符蓝色、无符号字符alpha=0xFF)
:红色(红色)、绿色(绿色)、蓝色(蓝色)、阿尔法(阿尔法){}
颜色(浮动红、浮动绿、浮动蓝、浮动alpha=1.0)
:红色(红色*255.0+.5)、绿色(绿色*255.0+.5)、蓝色(蓝色*255.0+.5)、阿尔法(阿尔法*255.0+.5){}
颜色(常量颜色和rhs)
:红色(右.红色),绿色(右.绿色),蓝色(右.蓝色),阿尔法(右.阿尔法){}
//运算符=和dtor自动生成
无符号字符&c_red(){返回红色}
无符号字符&c_green(){返回绿色}
无符号字符&c_blue(){return blue_;}
无符号字符&c_alpha(){return alpha;}
const unsigned char&c_red()const{return red}
const unsigned char&c_green()const{return green}
const unsigned char&c_blue()const{return blue}
const unsigned char&c_alpha()const{return alpha_;}
void set_f_red(float val){red_=val*255.0+.5;}
void set_f_green(float val){green_=val*255.0+.5;}
void set_f_blue(float val){blue_=val*255.0+.5;}
无效集_f_alpha(float val){alpha_=val*255.0+.5;}
float get_f_red()常量{return red_/255.0;}
float get_f_green()常量{return green_/255.0;}
float get_f_blue()常量{return blue_/255.0;}
float get_f_alpha()常量{return alpha_/255.0;}

unsigned int rgba(){return(red)您想为所有可能的情况创建一个类。这是错误的。一个类可以很好地处理所有这些情况

首先,你的GPU会期望颜色数据有4倍[0,1]的浮动,2,浮动[0,1]比[0,255]RGB颜色精确得多。这意味着从浮动0,1到字符0,255是有损的。这两个事实意味着你实际上别无选择,只能使用4倍[0,1]作为实现。是否另外为[0255]提供访问器和构造函数取决于您

其次,只需将A默认为1,就可以在同一个类中轻松支持RGB和RGBA—这样,任何不想处理A的人都不必这样做。

OOver engineering More,呃?:)只需注意,作为一个例子,你写的东西完全可以在C++中完成,有一点piml习惯用法和接口。