C++开发初级


1323 浏览 5 years, 10 months

7 嵌套类

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

嵌套类

类定义不仅可以包含方法以及成员,您还可以编写嵌套类以及嵌套结构、声明typedef或者创建枚举类型。类中声明的一切内容都具有类作用域。如果声明的内容是public,那么可以在类外面使用ClassName::作用域解析语法访问。 可在类的定义中提供另一个类定义。例如,您可能认为SpreadsheetCell类实际上是Spreadsheet类的一部分,可以这样定义这两个类:

class Spreadsheet
{
 public:

  class SpreadsheetCell
    {
    public:
      SpreadsheetCell();
      SpreadsheetCell(double initialValue);
      // .......
    protected:
      double mValue;
      string mString;
      mutable int mNumAccesses;
    };

  Spreadsheet(const SpreadsheetApplication& theApp,
          int inWidth = kMaxWidth, int inHeight = kMaxHeight);
  Spreadsheet(const Spreadsheet& src);
  ~Spreadsheet();
  // ......
}; 

代码取自 NestedClasses\Spreadsheet.h

现在SpreadsheetCell类定义位于Spreadsheet类内部,因此在Spreadsheet类外面引用SpreadsheetCell必须用Spreadsheet::作用域限定名称,即使在方法定义的时候也是如此。例如,默认构造函数应该是这样的:

Spreadsheet::SpreadsheetCell::SpreadsheetCell() : mValue(0), mNumAccesses(0)
{
}

代码取自 NestedClasses\Spreadsheet.h

这个语法很笨拙。例如, SpreadsheetCell()运算符的定义应该是这样的:

Spreadsheet::SpreadsheetCell& Spreadsheet::SpreadsheetCell::operator=(const SpreadsheetCell& rhs)
{
  if (this == &rhs) {
    return *this;
  }
  mValue = rhs.mValue;
  mString = rhs.mString;
  mNumAccesses = rhs.mNumAccesses;
  return *this;
}

代码取自 NestedClasses\Spreadsheet.cpp

实际上,在Spreadsheet类中方法的返回类型(不是参数)也必须使用这一语法:

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

代码取自 NestedClasses\Spreadsheet.cpp

为了避免这一笨拙的语法,可以使用typedef将Spreadsheet::SpreadsheetCell重命名为容易管理的名称,例如SCell:

typedef Spreadsheet::SpreadsheetCell SCell;

代码取自 NestedClasses\Spreadsheet.h

应该在Spreadsheet类定义的外部,否则就必须用Spreadsheet::将typedef名称本身限定为Spreadsheet:: SCell,这样做并没有什么好处!

现在,构造函数看起来应该是这样的:

SCell::SpreadsheetCell() : mValue(0), mNumAccesses(0)
{
}

代码取自 NestedClasses\Spreadsheet.cpp

普通的访问控制也适用于嵌套类定义。如果声明了private或者protected嵌套类,这个类只能在包含它的类中使用。

通常嵌套类定义只适用于微小的类。如果将类似于SpreadsheetCell的类作为嵌套类实在是太笨拙了。