我正在开发一款游戏引擎,目前我一直在设计IO系统。我已经做到了,引擎本身并不处理任何文件格式,而是让用户通过在内部创建具有适当命名函数的*.dll
文件来实现他想要的任何内容。虽然这本身并不是什么问题,但我主要担心的是在发动机使用过程中可能会出现的影响。
我设计了一个简单的resource
接口作为用户可以想到的所有内容的基类,我试图通过创建专用于公共数据类型的简单子类来扩展它,因此用户不需要自己实现基础知识(目前我正在考虑audio
,image
,data
和mesh
)。从audio
课开始,我偶然发现了一个特殊的问题,同时试图决定应该以什么类型存储有关采样率的信息。通常的单位是赫兹,所以我决定将其设为unsigned int
。
但是这里有一点问题 - 如果用户试图将其设置为千赫兹怎么办?让我们假设一些抽象文件格式可以暂时将它存储在两个单元中。我已经创建了一个简单的包装类来命名单元类型:
class hertz{
private:
unsigned int value;
hertz(){};
public:
operator unsigned int();
hertz(unsigned int value);
};
并决定让用户也使用kHz:
class kilohertz{
private:
float value;
kilohertz(){};
public:
operator hertz();
kilohertz(float value);
};
虽然audio
类中允许用户设置采样率的函数声明为track& samplingRate(units::hertz rate);
。用户必须通过明确说出他正在使用的数量级来调用它:
someAudioFile.samplingRate(hertz(44100));
someAudioFile.samplingRate(kilohertz(44.1));
我的问题是:
有没有更好的方法强制用户以简单而优雅的方式使用测量单位?一个设计模式可能,或者巧妙地使用typedef?
请注意,在创建引擎的过程中,我可能需要更多与Hertz不兼容的单元。从我的头脑中 - 我可能希望用户能够通过units::rgb(123,42,120)
和units::hsl(10,30,240)
设置像素颜色。
我已经尝试寻找可行的答案并且只找到了this question,但OP只需要数量级而不确保单位与其他单位不兼容。
另请注意,我使用的是旧C++
版本,而不是C++11
。虽然在任何版本中发布有效的解决方案都很棒,但如果我也可以使用它会很好:)
答案 0 :(得分:25)
我知道你提到过你没有使用C ++ 11,但是其他人在看这个问题可能是,所以这里是使用用户定义文字的C ++ 11解决方案:
#include <iostream>
using namespace std;
class Frequency
{
public:
void Print() const { cout << hertz << "Hz\n"; }
explicit constexpr Frequency(unsigned int h) : hertz(h) {}
private:
unsigned int hertz;
};
constexpr Frequency operator"" _Hz(unsigned long long hz)
{
return Frequency{hz};
}
constexpr Frequency operator"" _kHz(long double khz)
{
return Frequency{khz * 1000};
}
int main()
{
Frequency(44100_Hz).Print();
Frequency(44.1_kHz).Print();
return 0;
}
输出:
44100Hz
44100Hz
答案 1 :(得分:8)
Boost“Units”库非常适合此类事物。
http://www.boost.org/doc/libs/1_55_0/doc/html/boost_units.html
答案 2 :(得分:4)
您可以使用factory design pattern来完成您要找的内容。您可以使用私有构造函数和几个静态方法创建一个频率类,这些方法将根据用户想要使用的单位构造对象。通过保持构造函数的私有性,用户必须明确声明其单位,这样可以减少用户错误的可能性。
#include <iostream>
using namespace std;
class frequency
{
public:
static frequency hertz(int hz)
{
return frequency(hz);
}
static frequency kilohertz(double kHz)
{
return frequency(kHz * KHZ_TO_HZ);
}
static frequency rpm(int rpm)
{
return frequency(rpm * RPM_TO_HZ);
}
int hz()
{
return m_hz;
}
private:
static const int KHZ_TO_HZ = 1000;
static const int RPM_TO_HZ = 60;
frequency(int hz) : m_hz(hz)
{
}
int m_hz;
};
int main()
{
wcout << frequency::hertz(44100).hz() << "Hz" << endl;
wcout << frequency::kilohertz(44.100).hz() << "Hz" << endl;
}