При определении вложенного класса вне его содержащего класса следует квалифицировать имя вложенного класса именем его содержащего класса:

// определение класса QueryResult как члена класса TextQuery

class TextQuery::QueryResult {

 // в области видимости класса не нужно квалифицировать имя

 // параметров QueryResult

 friend std::ostream&

  print(std::ostream&, const QueryResult&);

public:

 // не нужно определять QueryResult::line_no; вложенный класс способен

 // использовать член своего содержащего класса без необходимости

 // квалифицировать его имя

 QueryResult(std::string,

  std::shared_ptr>,

  std::shared_ptr>);

 // другие члены, как в разделе 12.3.2

};

Единственное изменение, внесенное в первоначальный класс, заключается в том, что в классе QueryResult больше не определяется переменная-член line_no. Члены класса QueryResult могут обращаться к этому имени непосредственно в классе TextQuery, таким образом, нет никакой необходимости определять его снова.

Пока не встретится фактическое определение вложенного класса, расположенное вне тела класса, этот класс является незавершенным типом (см. раздел 7.3.3).

Определение членов вложенного класса

В этой версии конструктор QueryResult() не определяется в теле класса. Чтобы определить конструктор, следует указать, что класс QueryResult вложен в пределы класса TextQuery. Для этого имя вложенного класса квалифицируют именем содержащего его класса:

// определение члена класса по имени QueryResult для класса по

// имени QueryResult, вложенного в класс TextQuery

TextQuery::QueryResult::QueryResult(string s,

                                    shared_ptr> p,

                                    shared_ptr> f):

 sought(s), lines (p), file(f) { }

Читая имя функции справа налево, можно заметить, что это определение конструктора для класса QueryResult, который вложен в пределы класса TextQuery. Сам код только сохраняет данные аргументов в переменных-членах и не делает больше ничего.

Определение статических членов вложенных классов

Если бы класс QueryResult объявлял статический член, его определение находилось бы вне области видимости класса TextQuery. Например, статический член класса QueryResult был бы определен как-то так:

// определение статического члена типа int класса QueryResult

// вложенного в класс TextQuery

int TextQuery::QueryResult::static_mem = 1024;

Поиск имен в области видимости вложенного класса

Во вложенном классе выполняются обычные правила поиска имен (см. раздел 7.4.1). Конечно, поскольку вложенный класс — это вложенная область видимости, для поиска у него есть дополнительные области видимости в содержащем классе. Такое вложение областей видимости объясняет, почему переменная-член line_no не определялась во вложенной версии класса QueryResult. Первоначальный класс QueryResult определял этот член для того, чтобы его собственные члены могли избежать необходимости записи TextQuery::line_no. После вложения определения класса результатов в класс TextQuery такое определение типа больше не нужно. Вложенный класс QueryResult может обратиться к переменной line_no без указания, что она определена в классе TextQuery.

Как уже упоминалось, вложенный класс — это тип-член содержащего его класса. Члены содержащего класса могут использовать имена вложенного класса таким же образом, как и любой другой тип-член. Поскольку класс QueryResult вложен в класс TextQuery, функция-член query() класса TextQuery может обращаться к имени QueryResult непосредственно:

// тип возвращаемого значения должен указать, что класс QueryResult

// теперь вложенный

TextQuery::QueryResult

TextQuery::query(const string &sought) const {

 // если искомое значение не найдено, возвратить указатель на этот

 // набор

 static shared_ptr> nodata(new set);

Перейти на страницу:

Похожие книги