【问题标题】:Compile time polymorphism with enums使用枚举编译时多态性
【发布时间】:2015-03-31 16:50:15
【问题描述】:

所以,这些问题与枚举继承有关,我在这里看到了很多主题,其中描述了如何编写支持继承的枚举的方法,但我认为这不是我的情况。

我找到了一些我想做的东西。所以我的想法是我有这个类,让它成为 OpenGL 纹理类(实际上是),并且有一个枚举表示纹理中一个属性的所有可能值。

class Texture
{
    public:
        enum Filter
        {
            LINEAR   = 1,
            BILINEAR = 2,
            ANISOTROPIC = 3
        };

    public:
        Texture(Filter _filter)
            : filter(_filter) 
        { }

    private:
        Filter filter;
};

以及继承它的类。派生类中的枚举必须重新定义,但我可以在基类的构造函数中进一步使用:

class Texture2d : public Texture
{
    public:
        enum Filter
        {
            LINEAR   = 1,
            BILINEAR = 2
        };

    public:
        Texture2d(Filter _filter)
            : Texture(_filter)
        { }
};

但是,当然,这不起作用,因为新创建的FilterTexture2d::Filter,而不是Texture::Filter

我尝试像这样使用enum class

class Texture
{
    public:
        enum class Filter;

    public:
        Texture(Filter _filter)
            : filter(_filter)
        { }

    private:
        Filter filter;
};

class Texture2d : public Texture
{
    public:
        enum Filter
        {
            LINEAR = 1,
            BILINEAR = 2
        };

    public:
        Texture2d(Filter _filter)
            : Texture(_filter)
        { }
};

但这真是愚蠢的想法。我认为,如果我只想扩展枚举,我会编写一些类包装器,但我也需要缩小枚举。所以问题是,如何让这个东西在编译时工作?这是主要问题 - 使这项工作在编译时工作。还有一个问题:实际上尝试做这样的事情是可以的,还是我必须检查我的应用程序的架构?

(所有答案将不胜感激)

【问题讨论】:

  • 第一行错字,有“Hello all)”
  • 您是否考虑过使用模板而不是继承,这样过滤器可以成为类的一部分,而不是将其作为枚举分开。
  • 在我看来,您正在使您的设计复杂化。保持简单(传统的“是”关系)。
  • 所以,我仍然在考虑建筑......问题是,例如,一种纹理具有某些属性,而另一种则没有。他们必须使用一个函数来设置 Opengl 中的实际值。但更糟糕的是,另一种类型本身并不是一个属性,而是该属性的一个或多个可能状态。所以,就是……实际上枚举是这样的:枚举类过滤器
  • enum class Filter { LINEAR = GL_LINEAR, NEAREST = GL_NEAREST, ... } 所以,实际上 enum 持有 opengl 定义,我需要持有它,或者在相反的情况下我会使用这样的函数:GLenum func(Filter filter) { switch(filter) { case LINEAR: return GL_LINEAR; //等等 } } 我不喜欢这种方式。

标签: c++ c++11 inheritance enums polymorphism


【解决方案1】:

我看不出您的代码有问题。
您只需在 Texture2d 的构造函数中添加演员表。

Texture2d(Filter _filter) // no Texture::Filter
    : Texture(static_cast<Texture::Filter>(_filter))
{ }

Texture t1(Texture::LINEAR);           // WORKS
Texture t2(Texture::BILINEAR);         // WORKS
Texture t3(Texture::ANISOTROPIC);      // WORKS

Texture2d t4(Texture2d::LINEAR);       // WORKS
Texture2d t5(Texture2d::BILINEAR);     // WORKS
Texture2d t6(Texture2d::ANISOTROPIC);  // ERROR

这是因为Texture2d::ANISOTROPIC 被解释为Texture::ANISOTROPIC,因为不存在Texture2d::Filter::ANISOTROPIC

由于Texture2ds 的构造函数都不接受Texture::Filter,因此会导致错误。

【讨论】:

  • 哦,谢谢,我不知道我怎么会失去它!)但是这种方法非常优雅吗?
  • @1243scrat 这取决于你对优雅的定义。它做你想做的事,而且很简单,所以我想这很好。
  • 是的,真的很好,非常感谢Axalo! =)
【解决方案2】:

枚举没有继承 - 所以扩展/缩减的想法是行不通的。您可以做的是在Texture2d 中提供它们之间的转换方法:

class Texture2d : public Texture {
public:
    enum class Filter {
        LINEAR, BILINEAR
    };

    Texture2d (Filter f)
    : Texture(convert(f))
    { }

private:
    Texture::Filter convert(Filter f) {
        switch(f) {
        case Filter::LINEAR: return Texture::Filter::LINEAR;
        // etc.
        default: 
            // ? Maybe throw? 
     }
};

让我们指定每个子类中的有效枚举列表。但是,如果您通常希望允许相同的内容,则可能会重复。

【讨论】:

  • 谢谢,我认为它也可以发生,但似乎 Axollo 方法更简单。无论如何,谢谢你,虽然这是很好的食物)
猜你喜欢
  • 2012-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多