我正在编写一个简单的类来处理我正在制作的小应用程序中的颜色。
这个类将有4个双成员变量,并且希望能够通过名称(即:r,g,b和a)或索引(0表示红色,1表示绿色等)来引用它们。 。
此外,能够使用大括号括起初始化列表进行初始化会很棒。
但是,我无法找到一种优雅而简洁的方法来编码。
这是我最好的尝试,它不漂亮。它也不处理无效索引。
struct Colour{
double r, g, b, a;
double& operator[](int i){
switch(i){
case 0:
return r;
break;
case 1:
return g;
break;
case 2:
return b;
break;
case 3:
return a;
break;
}
}
/* ... */
};
/* ... */
int main(){
Colour c = {1.0, 2.0, 3.0, 4.0};
std::cout << c.g << std::endl;
c[1] = 10.0;
std::cout << c.g << std::endl;
return 0;
}
虽然这确实有效,但我想知道是否有更多(a)优雅,(b)高性能(因为这个应用程序主要处理像素操作)的方式来做到这一点。
非常感谢你。
你的代码看起来很漂亮。它可以在switch语句中使用默认情况。我喜欢你专注于为类用户创建一个灵活的工作流程,但一般来说,在C ++中,没有免费午餐这样的东西。如果你想要更多的选择,你的课将变得更加复杂。
但是,自从你提出以来。如果你的优雅意味着保持你的课堂定义简洁......
// C++'11
struct Colour
{
double v[4];
double& r = v[0];
double& g = v[1];
double& b = v[2];
double& a = v[3];
double& operator[](int i)
{
assert(i >= 0 && i < 4); // #include <assert.h>
return v[i];
}
};
void test()
{
Colour c{ 1.0, 2.0, 3.0, 4.0 };
std::cout << c.b << std::endl;
}
我对此有的问题:
Colour c{ 1.0, 2.0, 3.0, 4.0, 5.0 }; // does not compile (good!)
double x = 5.0;
Colour c{ 1.0, 2.0, 3.0, 4.0, x }; // compiles (...bad)
顺便说一句,断言在调试模式下抛出一个有用的异常,但在发布模式下编译时,检查被删除(通过标志)。
如果是我,我会使用你的代码并添加边界检查。
对于性能,此时您唯一需要关注的是不使用低效算法。稍后,如果您已完成分析并且此类是瓶颈(LOL),我们可以尝试对其进行优化。顺便说一句,代码简洁和优化不是朋友。
如果有明确定义的整数项目数量有限,则可以使用pre-C ++ 11枚举器。您的枚举器可以是RED = 1,GREEN = 2,BLUE = 3等等。因此,您的代码将更具可读性,但仍保持整数效率。
您需要转换为字符和/或字符串的唯一时间是您要将数据输入或输出到文件。在这种情况下,您只需要转换功能。但据推测,输入/输出不是使用这些值的主要部分,因此转换功能的性能不会受到关注。
这是我对此基于@HumphreyWinnebago解决方案的看法,但试图解决尺寸的增加。我们的想法是使用带有数组和未命名结构的联合。通过这种方式,您可以按名称访问struct元素,按索引访问数组元素。
#include <iostream>
#include <cassert>
#include <cstdint>
#include <array>
template<typename T>
union Colour {
std::array<T,4> v;
struct { T r,g,b,a; };
T& operator[](std::size_t i) {
assert(i < 4);
return v[i];
}
};
int main() {
Colour<uint8_t> c{ 1, 2, 3, 4 };
std::cout << int(c.b) << "\n";
std::cout << int(c[1]) << "\n";
std::cout << sizeof c << "\n";
Colour<double> d{ 1.1, 2.2, 3.3, 4.4 };
std::cout << d.b << "\n";
std::cout << d[1] << "\n";
std::cout << sizeof d << "\n";
return 0;
}
我担心遗憾的是,这很大程度上依赖于结构的实现特定对齐,但我相信它可能是一个有趣的解决方案。