按名称或索引引用成员变量

时间:2017-12-17 17:34:06

标签: c++ class reference

我正在编写一个简单的类来处理我正在制作的小应用程序中的颜色。

这个类将有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)高性能(因为这个应用程序主要处理像素操作)的方式来做到这一点。

非常感谢。

3 个答案:

答案 0 :(得分:3)

你的代码看起来很漂亮。它可以在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),我们可以尝试对其进行优化。顺便说一句,代码简洁和优化不是朋友。

答案 1 :(得分:1)

如果有明确定义的整数项目数量有限,则可以使用pre-C ++ 11枚举器。您的枚举器可以是RED = 1,GREEN = 2,BLUE = 3等等。因此,您的代码将更具可读性,但仍能保持整数效率。

您需要转换为字符和/或字符串的唯一时间是您要将数据输入或输出到文件。在这种情况下,您只需要转换功能。但据推测,输入/输出不是使用这些值的主要部分,因此转换功能的性能不会受到关注。

答案 2 :(得分:0)

这是我对此基于@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;
}

我担心遗憾的是,这很大程度上依赖于结构的实现特定对齐,但我相信它可能是一个有趣的解决方案。