C++开发初级


1186 浏览 5 years, 4 months

4.1 Spreadsheet类及内存创建

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

Spreadsheet类

前面介绍了SpreadsheetCell类,本章进一步编写Spreadsheet类。与SpreadsheetCell类相似,Spreadsheet类将在本章逐步改进。因此,不同的尝试并非总是为了说明编写类的最佳方法。最初的Spreadsheet类只是一个SpreadsheetCell类型的二维数组,其中具有设置以及获取Spreadsheet中特定位置单元格的方法。

尽管大多数电子表格应用程序为了指定单元格会在一个方向上使用字母而在另一个方向上使用数字,但此处的Spreadsheet在两个方向上都使用数字。下面是这个简单Spreadsheet类的第一个定义:

// Spreadsheet.h
#include "SpreadsheetCell.h"
class Spreadsheet
{
 public:
  Spreadsheet(int inWidth, int inHeight);
  void setCellAt(int x, int y, const SpreadsheetCell& cell);
  SpreadsheetCell getCellAt(int x, int y);

 protected:
  bool inRange(int val, int upper);
  int mWidth, mHeight;
  SpreadsheetCell** mCells;
};

代码取自 Spreadsheet\Spreadsheet.h

Spreadsheet类中,mCell数组使用的是普通指针。这种做法贯穿整个章节,其目的是说明因果关系并解释如何在类中处理动态内存分配。在产品代码中,应该使用标准C++容器,例如前面简要介绍的std::vector,这一内容将在后面详细讲述。

注意Spreadsheet类并没有包含一个标准的SpreadsheetCell类型的二维数组,而是包含了一个SpreadsheetCell**。原因是Spreadsheet对象的尺度可能不同,因此类的构造函数必须能够根据客户指定的宽度和高度动态分配二维数组。为了动态分配二维数组,可以编写如下代码:

Spreadsheet::Spreadsheet(int inWidth, int inHeight) :
  mWidth(inWidth), mHeight(inHeight)
{
  mCells = new SpreadsheetCell* [mWidth];
  for (int i = 0; i < mWidth; i++) {
    mCells[i] = new SpreadsheetCell[mHeight];
  }
}

代码取自 Spreadsheet\Spreadsheet.cpp

堆栈是名为s1的Spreadsheet分配的内存如下图所示,宽度为4,高度为3。

设置以及获取方法的实现简捷明了:

void Spreadsheet::setCellAt(int x, int y, const SpreadsheetCell& cell)
{
  if (!inRange(x, mWidth) || !inRange(y, mHeight)) {
    throw std::out_of_range("");
  }

  mCells[x][y] = cell;
}

SpreadsheetCell Spreadsheet::getCellAt(int x, int y)
{
  if (!inRange(x, mWidth) || !inRange(y, mHeight)) {
    throw std::out_of_range("");
  }
  return mCells[x][y];
}

代码取自 Spreadsheet\Spreadsheet.cpp

注意这两个方法将inRange()方法用作辅助方法,检测电子表格中x以及y坐标是否有效。试图访问索引范围外的数组元素将导致程序故障。这个示例使用了前面提到并将在后面详细讲述的异常。