DECIMAL包装类






3.35/5 (10投票s)
一个简单的 DECIMAL 包装类,适用于 C++ 代码与 VB 脚本/OLE 自动化代码等进行接口交互。
引言
这是一个简单的实用工具类,它封装了 OLE 自动化类型 DECIMAL
。其目的是让用户摆脱 ::VarDecXXX()
调用,并使 DECIMAL
"表现得像 int
一样"。
互操作性
我的类 Decimal
公开继承自 DECIMAL
。这样做的好处是,任何可以使用 DECIMAL
的地方,你也可以使用 Decimal
。这使得该类与原始 COM 接口完全可互操作。
与 ATL 不同,我没有重载 *取地址* 运算符 (operator&
),因此无需使用 CAdapt<>
来使该类适应 STL 容器。
接口
所有方法和构造函数都具有 throw()
属性,即,任何方法都不会抛出异常。但是,在调试构建中,可能会触发 assert
。除以零就是其中之一。但是你已经知道不应该除以零了,对吧?
所有返回 Decimal&
值的方法都返回对 *this
的引用。因此,可以堆叠此类方法/操作。
构造函数
有十个构造函数。它们是:
Decimal()
将对象初始化为值 0。
Decimal(const DECIMAL& decValue)
使用参数
decValue
中包含的值初始化对象。Decimal(char nValue)
Decimal(short nValue)
Decimal(long nValue)
Decimal(unsigned char nValue)
Decimal(unsigned short nValue)
Decimal(unsigned long nValue)
使用参数
nValue
中包含的整数值初始化对象。Decimal(float fValue)
Decimal(double fValue)
使用参数
nValue
中包含的实数值初始化对象。
变异运算符
定义了以下运算符,它们的行为与 int
相同(因此我不会解释它们的用法和功能!)
Decimal& operator = (char nValue)
Decimal& operator = (short nValue)
Decimal& operator = (long nValue)
Decimal& operator = (unsigned char nValue)
Decimal& operator = (unsigned short nValue)
Decimal& operator = (unsigned long nValue)
Decimal& operator = (float fValue)
Decimal& operator = (double dValue)
Decimal& operator += (const DECIMAL& decRHS)
Decimal& operator -= (const DECIMAL& decRHS)
Decimal& operator *= (const DECIMAL& decRHS)
Decimal& operator /= (const DECIMAL& decRHS)
Decimal operator++(int)
Decimal operator--(int)
Decimal& operator++()
Decimal& operator--()
每个运算符的操作都如同它们是为 int
定义的一样。
变异方法
bool FromString(LPCOLESTR lpszNum, LCID lcid = 0)
使用区域设置标识符
lcid
解析由lpszNum
指向的字符串。解析后的值在返回之前会赋给this
对象。如果此函数因字符串格式错误而失败,则返回值为
false
。如果区域设置标识符
lcid
为0
,则将使用默认系统区域设置来解析字符串。Decimal& MakeAbsolute()
将此值设为绝对值。
Decimal& MakeNegative()
将此值设为负值。
Decimal& MakeInteger()
通过删除小数部分将此值设为整数。此函数的语义如下:*如果值为负数,则返回小于或等于此值的第一个负整数。*(语义描述复制并改编自 MSDN 文档。原始文本请参阅
VarDecInt
的手册页。)Decimal& MakeFixed()
通过删除小数部分将此值设为整数。此函数的语义如下:*如果值为负数,则返回大于或等于此值的第一个负整数。*(语义描述复制并改编自 MSDN 文档。原始文本请参阅
VarDecFix
的手册页。)Decimal& MakeRound(int n)
将此值四舍五入到第
n
位小数。请注意,
n
必须大于或等于零。
非变异方法
以下函数是非变异的。它们与上面描述的变异方法相关,因此我在此处仅提及它们。例如,如果下面提及的方法名为 Absolute
,则请参阅上面 MakeAbsolute
的文档。这些方法都具有不修改当前值的共同属性。相反,它们会创建一个临时值,该值被修改并返回。
Decimal Absolute() const
Decimal Negative() const
Decimal Integer() const
Decimal Fixed() const
Decimal Round() const
检查器
bool IsNegative() const
如果此值为负数,则返回
true
的谓词。bool IsZero() const
如果此值为负数,则返回
true
的谓词。这是测试Decimal
是否为零的最快方法。BSTR ToString(LCID lcid = 0) const
使用指定的区域设置将此值转换为
BSTR
字符串。如果区域设置标识符lcid
为零,则将使用系统默认区域设置。
自由函数
以下自由函数,虽然逻辑上是 Decimal
的成员,但其工作方式如同为 int
设计的一样。
Decimal operator + (const DECIMAL& decRHS, const DECIMAL& decLHS)
Decimal operator - (const DECIMAL& decRHS, const DECIMAL& decLHS)
Decimal operator * (const DECIMAL& decRHS, const DECIMAL& decLHS)
Decimal operator / (const DECIMAL& decRHS, const DECIMAL& decLHS)
bool operator < (const DECIMAL& decRHS, const DECIMAL& decLHS)
bool operator > (const DECIMAL& decRHS, const DECIMAL& decLHS)
bool operator <= (const DECIMAL& decRHS, const DECIMAL& decLHS)
bool operator >= (const DECIMAL& decRHS, const DECIMAL& decLHS)
bool operator == (const DECIMAL& decRHS, const DECIMAL& decLHS)
bool operator != (const DECIMAL& decRHS, const DECIMAL& decLHS)
实现细节
我没有在我的代码中进行任何算术计算。我只是使用 OLE 自动化函数来操作 DECIMAL
。我所做的只是将它们全部组合成一个薄薄的 C++ 包装类,这使得 DECIMAL
更愉快地使用。语法糖让软件更甜美。
如果你快速查看源文件,你会发现它是一个非常薄的包装器,据我所知,它增加的运行时间开销非常小。但是请,如果我错了,请纠正我。
买方注意
在使用此代码之前,您可能需要了解一些事项。
验证/断言
此代码目前使用 C 库版本的 assert
(以及我自己的依赖于 assert
的宏 verify
)。您可能希望在 ATL 或 MFC 环境中使用此代码之前更改它。一个简单的“查找和全部替换”应该可以解决问题。
变体
我没有包含任何处理 VARIANT
的方法。我想要一个简单而干净的接口。如果我需要与 VARIANT
的任何互操作性,我会添加该方法。在那之前,祝你好运——或者自己编写。
字符串
正如你可能已经注意到的,我只支持接口中的 BSTR
字符串。原因很简单;我打算在接近 VB[Script](以及可能其他奇怪的环境)的阴影区域中使用此代码,而 BSTR
是首选的字符串。我不相信臃肿的接口,所以除非我真的需要,否则我不会添加对任何其他类型字符串的支持。如果我需要,我会更新此源代码。如果你在我之前需要它,那么,你已经有了源代码!
VC6
我已将 VC6 作为此文章的关键字。但我承认我尚未针对该编译器进行测试。但由于我没有使用任何花哨的模板或其他新颖奇特的功能,我相信此代码在 VC6 中也能正常工作。事实上,我在另一个项目中有一个此类的旧版本,它在 VC6 中编译得很好。考虑到我删除了许多冗余代码,此类应该仍然可以编译。这是最高水平的质量保证。
四舍五入硬币
头文件中有一个名为 RoundToSmallestCoin
的自由函数。这是我在工作中编写的 POS 软件中使用的函数。我把它保留在此文件中是因为我懒惰。如果你觉得它使你的代码臃肿,只需选中它并按下删除按钮即可。
参考文献
Marc Clifton 写了一篇关于 decimal 类的类似文章。如果您的代码不打算与 COM/OLE 自动化环境一起使用,他的实现是完美的。您可以在此处找到他的文章。
免责声明和许可授予
免责声明
本文和源代码不提供任何形式的保证。对于数据损坏、硬件损坏或人身伤害,我概不负责。事实上,如果您使用此源代码,您不能要求我承担任何责任。
许可授予
但是,如果您觉得这段代码有用,并且我们有缘相遇,如果您请我喝啤酒(最好是我选择的啤酒),我不会说“不,谢谢”。但是,这不是必需的。如果可以接受,这是啤酒软件,否则就是免费软件。