8.6.3 实现CBox类(2)
2. 合并CBox对象
现在需要解决的问题是重载+、*、/和%运算符,下面依次实现它们。我们已经从Ex8_06.cpp获得的加法操作具有下面的原型:
- CBox operator+(const CBox& aBox); //
Function adding two CBox objects
虽然原来实现的加法运算符并不是理想的解决方案,但我们还是要继续使用,以避免使CBox类过于复杂。最好是设计一个程序来检查两个操作数是否有尺寸相同的面,如果有,则顺着这样的面进行连接,但编码工作会很麻烦。当然,如果这是个实际的应用程序,那么我们可以稍后再来开发更好的加法操作,并替换现有的版本,而使用原来版本编写的任何程序都无需修改就能继续运行。类的接口与实现相分离,对于有效的C++(www.cppentry.com)编程(www.cppentry.com)具有决定性意义。
注意,本书不再详述减法运算符。这是个明智的决定,可以避免实现过程中固有的复杂性。如果您实在对此充满热情,而且觉得实现该运算符切合实际,那么可以试一下,但需要决定当得到的体积结果为负数时应做什么事情。如果允许体积为负数,则需要解决哪些箱子的尺寸可以是负数,以及在随后的操作中如何处理这类箱子等问题。
乘法操作非常容易,只是创建一个可包含n个箱子的箱子而已,其中n是乘数。最简单的解决方案是保持对象的m_Length和m_Width不变,然后使高度乘以n从而得到新的CBox对象。我们可以使该函数更智能化一些,那就是检查一下乘数是不是偶数,如果是,则使m_Width加倍,这样箱子将肩并肩堆放,然后只需使m_Height乘以n的1/2即可。该机制如图8-6所示。
|
| (点击查看大图)图 8-6 |
当然,我们不需要检查新对象的长度和宽度哪个更大,因为构造函数会自动将较大的数值挑出来。我们可以将operator*()函数编写成左操作数是CBox对象的成员函数:
- // CBox multiply operator this*n
- CBox operator*(int n) const
- {
- if(n % 2)
- return CBox(m_Length, m_Width, n*m_Height);
- // n odd
- else
- return CBox(m_Length, 2.0*m_Width, (n/2)*m_Height); // n even
- }
在这里,我们使用%运算符判断n是偶数还是奇数。如果是奇数,则n % 2的值是1,if语句为true。如果是偶数,则n % 2的值是0,if语句为false。
现在即可使用刚才编写的语句,实现左操作数是整数的版本。我们可以将该函数编写成普通的非成员函数:
- // CBox multiply operator n*aBox
- CBox operator*(int n, const CBox& aBox)
- {
- return aBox*n;
- }
该版本的乘法操作仅仅将操作数的顺序颠倒了一下,这样就可以直接使用前面的乘法运算符版本。至此,为CBox对象定义的算术运算符就全部完成了。最后可以看看如何实现两个分解运算符函数operator/()和operator%()。
3. 分解CBox对象
前面曾经说过,除法操作确定左操作数指定的CBox对象可以包含多少个右操作数指定的CBox对象。为了使问题相对简单,我们假设所有CBox对象都是以正常层序包装的-- 即高度是垂直的,另外假设它们都是以相同的朝向包装的-- 即长度方向相同。如果没有这些假设,问题可能变得相当复杂。
这样,该问题实际上就变为求出一层可以放多少个右操作数对象,再求出左操作数对象中可以放几层。
我们可以将该运算符编写成下面这样的成员函数:
- int operator/(const CBox& aBox)
- {
- int tc1 = 0; // Temporary for number
in horizontal plane this way - int tc2 = 0; // Temporary for number
in a plane that way -
- tc1 = static_cast<int>((m_Length / aBox.m_Length))*
- static_cast<int>((m_Width / aBox.m_Width)); // to fit this way
-
- tc2 = static_cast<int>((m_Length / aBox.m_Width))*
- static_cast<int>((m_Width / aBox.m_Length)); // and that way
-
- //Return best fit
- return static_cast<int>((m_Height/aBox.m_Height)*(tc1>tc2 tc1 :
- tc2));
- }
该函数首先求出左、右操作数CBox对象的长度方向相同时,一层可以容纳多少个右操作数CBox对象,并将结果存入tc1。然后再求出右操作数CBox的长度与左操作数CBox的宽度同向时,一层可以容纳多少个右操作数对象。最后,使tc1和tc2中较大的数乘以可以包装的层数,并返回得到的数值。该过程如图8-7所示。
我们看到有两种将bBox放入aBox的可能性:一是bBox的长度与aBox的长度同向,二是bBox的长度与aBox的宽度同向。从图8-7可以看出,最好的包装方式是旋转bBox,用它的宽度去除aBox的长度。
|
| (点击查看大图)图 8-7 |