c++ - 为一个模板类提供多个模型以供选择

标签 c++ templates inheritance c++11

我目前正在使用模板来构建颜色类。我正在使用模板,因为可以使用不同的 color spaces 来定义和存储颜色。或 color models .

基本上,我想出了一个类,该类将颜色模型类作为模板参数并从中继承,以便访问特定于模型的方法,如 red()green ()blue() 用于 RGB 模型,或 hue()saturation()value( ) 用于 HSV 模型。我还编写了一些模型类以及一些用于颜色和模型转换器函数的便利类型定义。

template <typename T>
class Color : public T {
public:
    typedef T Model;

    using T::T;

    // This is meant to convert colors with different models
    template <typename U>
    explicit Color(const Color<U>& c);
};

class RGB {
public:
    static constexpr auto name = "RGB";

    RGB() = default;
    RGB(unsigned int argb);
    RGB(unsigned int r, unsigned int g, unsigned int b, unsigned int a = 0xFF);

    RGB lighter(double factor = 1.2) const;
    RGB negative() const;
    RGB greyscale() const;

    unsigned int argb() const;
    unsigned int red() const;
    unsigned int green() const;
    unsigned int blue() const;
    unsigned int alpha() const;

private:
    unsigned int m_argb;
};

class HSV {
public:
    static constexpr auto name = "HSV";

    HSV() = default;
    HSV(unsigned int h, unsigned int s, unsigned int v, unsigned int a = 0xFF);

    HSV lighter(double factor = 1.2) const;
    HSV complementary() const;
    HSV greyscale() const;

    unsigned int hue() const;
    unsigned int saturation() const;
    unsigned int value() const;
    unsigned int alpha() const;

private:
    unsigned int m_h, m_s, m_v, m_a;
};

typedef Color<RGB> RGBColor;
typedef Color<HSV> HSVColor;

template<typename From, typename To>
To ColorModelConverter(From model);
template<>
RGB ColorModelConverter<HSV, RGB>(HSV model);
template<>
HSV ColorModelConverter<RGB, HSV>(RGB model);

起初这似乎是个好主意。然而,出现了多个问题,首先是整个事情看起来很丑陋和注定。

事实上,我有两个主要问题,第一个如下:如何让模型的方法返回颜色而不是模型(它们自己的类型)?

Color<RGB> greyscale() const;
// ... instead of ...
RGB greyscale() const;

另一个问题在于不同模型之间的颜色转换:

template <typename U>
explicit Color(const Color<U>& c);

我本来打算在这个构造函数中使用模型转换器函数,但我无法设置它。

此设计背后的想法是能够创建新的颜色模型,使用与现有模型之间的适当转换器,并将它们与 Color 类(具有模型类型的 typedef 和通用转换构造函数)一起使用。 [edit] 为了创建一个新的颜色模型,不需要(而且根本不应该)修改任何现有的类(模型或颜色类),但可能需要编写相应的转换器。 [编辑]

所以我的问题是:我的设计是否可以修复并且基本上是一个好的设计(修复后)?如果没有,我有什么可能来实现与我指定的功能相同的功能?

最佳答案

来自您的评论之一:

There is no code that should not care about the model used.

我认为这就是问题的要点。

如果没有模型无关的 Color 客户端代码,那么模板和面向对象都没有意义。

您基本上已经创建了两个完全独立的类,它们的名称中恰好有尖括号。只需创建两个完全独立的非模板类RgbColorHsvColor。它应该使您的整个代码更加清晰。

The main benefit would be to have a converter constructor instead of functions, without modifying existing models if you add new ones (to add converters).

我认为这不会带来任何实际好处,因为您仍然必须显式实现从模型 X 到模型 Y 的每一次转换。在任何情况下都没有真正的自动化。

一个更简洁的解决方案是编写非成员非好友转换函数:

RgbColor ToRgb(HsvColor const &color);
HsvColor ToHsv(RgbColor const &color);

Non-member non-friend 意味着如果添加新模型,无需更改任何类。这进一步意味着所有转换在客户端代码中都清晰可见,并且不太可能发生意外的不需要的转换。

另一个优势是支持单向转换。例如,您以后可能需要不支持 alpha 的 RGB 颜色类。 RgbColorNoAlpha 的实例应该可以转换为 RgbColor,但反之则不行。通过 缺少 RgbColorNoAlpha ToRgbColorNoAlpha(RgbColor const &color),代码可以轻松满足此要求。

关于c++ - 为一个模板类提供多个模型以供选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25229475/

相关文章:

c++ - 如何检查文件是否被压缩?

c++ - 无法使用带有boost C++的ubuntu中的完整路径打开文件

c++ - 从 C++ 控制台应用程序创建可用程序

c++ - 从属模板名称参数替换

c++ - 函数模板的隐式实例化

c++ - 在 C++ 中使隐式转换运算符优于另一个

c# - 泛型方法从父类(super class)获取参数类型

c++ - 无效的 fastbin 条目(免费)

c++ - 派生类中需要构造函数参数的成员对象如何初始化?

java - 继承,每一步之后发生了什么