使用枚举编译时多态性
Compile time polymorphism with enums
因此,问题与枚举继承有关,我在这里看到了很多主题,其中描述了如何编写支持继承的枚举的方法,但我认为这不是我的情况。
我找到了一些我想做的东西。所以我的想法是我有 class,让它成为 OpenGL 纹理 class(实际上它是)并且有一个枚举代表纹理中一个 属性 的所有可能值。
class Texture
{
public:
enum Filter
{
LINEAR = 1,
BILINEAR = 2,
ANISOTROPIC = 3
};
public:
Texture(Filter _filter)
: filter(_filter)
{ }
private:
Filter filter;
};
和继承它的class。派生 class 中的枚举必须重新定义,但我可以在基础 class 的构造函数中进一步使用:
class Texture2d : public Texture
{
public:
enum Filter
{
LINEAR = 1,
BILINEAR = 2
};
public:
Texture2d(Filter _filter)
: Texture(_filter)
{ }
};
但是,当然,这不起作用,因为新创建的 Filter
是 Texture2d::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)
{ }
};
但这真是个愚蠢的想法。我想,如果我只想扩展枚举,我会写一些 class 包装器,但我也需要缩小枚举。那么问题来了,如何让这个东西在编译时工作呢?这是主要问题 - 让这个在编译时工作。还有一个问题:实际上尝试做这样的事情是可以的,或者我必须检查我的应用程序的架构?
(所有答案将不胜感激)
我没有发现你的代码有问题。
您只需在 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
不存在。
并且由于 Texture2d
中的 none 个构造函数接受 Texture::Filter
,因此会导致错误。
枚举没有继承 - 所以 extending/reducing 想法是行不通的。您可以做的是在它们之间的 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?
}
};
让您在每个子类中指定有效枚举列表。如果您通常希望允许相同的,则可能会重复。
因此,问题与枚举继承有关,我在这里看到了很多主题,其中描述了如何编写支持继承的枚举的方法,但我认为这不是我的情况。
我找到了一些我想做的东西。所以我的想法是我有 class,让它成为 OpenGL 纹理 class(实际上它是)并且有一个枚举代表纹理中一个 属性 的所有可能值。
class Texture
{
public:
enum Filter
{
LINEAR = 1,
BILINEAR = 2,
ANISOTROPIC = 3
};
public:
Texture(Filter _filter)
: filter(_filter)
{ }
private:
Filter filter;
};
和继承它的class。派生 class 中的枚举必须重新定义,但我可以在基础 class 的构造函数中进一步使用:
class Texture2d : public Texture
{
public:
enum Filter
{
LINEAR = 1,
BILINEAR = 2
};
public:
Texture2d(Filter _filter)
: Texture(_filter)
{ }
};
但是,当然,这不起作用,因为新创建的 Filter
是 Texture2d::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)
{ }
};
但这真是个愚蠢的想法。我想,如果我只想扩展枚举,我会写一些 class 包装器,但我也需要缩小枚举。那么问题来了,如何让这个东西在编译时工作呢?这是主要问题 - 让这个在编译时工作。还有一个问题:实际上尝试做这样的事情是可以的,或者我必须检查我的应用程序的架构?
(所有答案将不胜感激)
我没有发现你的代码有问题。
您只需在 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
不存在。
并且由于 Texture2d
中的 none 个构造函数接受 Texture::Filter
,因此会导致错误。
枚举没有继承 - 所以 extending/reducing 想法是行不通的。您可以做的是在它们之间的 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?
}
};
让您在每个子类中指定有效枚举列表。如果您通常希望允许相同的,则可能会重复。