C++开发中级


901 浏览 5 years, 11 months

4.6 考虑将来

版权声明: 转载请注明出处 http://www.codingsoho.com/

考虑将来

SpreadsheetCell层次结构的新实现从面向对象设计的观点来看当然是一个进步。但是,对于实际的电子表格程序来说,还不够充分,主要有以下几个原因:

首先,即使不考虑改进设计,现在仍然缺少一个功能:将某个单元格类型转换为其他类型的能力。由于将单元格分为两类,单元格对象的结合变得更松散。为了提供将DoubleSpreadsheetCell转换为StringSpreadsheetCell的功能,应该添加一个类型转换构造函数,这个构造函数类似于复制构造函数,但是参数不是同类对象的引用,而是同级类对象的引用:

class StringSpreadsheetCell : public SpreadsheetCell
{
 public:
  StringSpreadsheetCell();
  StringSpreadsheetCell(const DoubleSpreadsheetCell& inDoubleCell);
};

通过类型转换构造函数,可以很方便地用DoubleSpreadsheetCell创建StringSpreadsheetCell。然而不要将其与类型转换混淆,类型转换无法将一个对象转换为同级类的另一个对象,除非您按照前面讲述的方法重载了类型转换运算符。
提示:您可以向上转型,有时也可以向下转型,但是无法在同级类之间转型,除非您改变了类型转换运算符的行为。

如何为单元格实现运算符重载是一个很有趣的问题,在此有几种可能的解决方案。其中一种方法是:针对每个单元格组合,实现每个运算符的重载版本。由于只有两个子类,因此这样做并不困难。可以编写一个operator+函数将两个双精度单元格相加,将两个字符串单元格相加,将双精度单元格与字符串单元格相加。

另一种方法是给出一种通用表示,前面的 实现已经将字符串作为标准化的通用类型表示。通过这种通用表示,一个operator+函数就可以处理所有情况。如果假定两个单元格相加的结果始终是字符串单元格,那么一个可能的实现如下所示:

const StringSpreadsheetCell operator+(const StringSpreadsheetCell& lhs, const StringSpreadsheetCell& rhs)
{
    StringSpreadsheetCell newCell;
    newCell.set(lhs.getString() + rhs.getString());
    return newCell;
}

只要编译器可以将特定的单元格转换为StringSpreadsheetCell,这个运算符就可以运行。考虑前面的示例,StringSpreadsheetCell构造函数采用DoubleSpreadsheetCell作为参数,如果这是operator+运行的唯一方法,那么编译器将自动执行转换。这意味着下面的代码可以运行,尽管operator+显式地用于StringSpreadsheetCell:

DoubleSpreadsheetCell myDbl;
myDbl.set(8.4);
StringSpreadsheetCell result = myDbl + myDbl;

当然,相加的结果实际上并不是将数字相加,而是将双精度单元格转换为字符串单元格然后将字符串相加,结果是一个值为8.4的StringSpreadsheetCell。
如果您对多态性还不确定,可运行这个示例的代码并获取答案。如果只是为了体验这个类的各种特性,前面示例中的main()函数是一个很好的起点。