Класс, определенный в теле функции, называют
На практике требование полностью определять члены в самом классе, существенно ограничивает сложность, а следовательно, и возможности функций-членов локального класса. Функции локальных классов редко имеют размер, превышающий несколько строк кода. Более длинный код функций труднее прочитать и понять.
Кроме того, в локальном классе нельзя объявлять статические переменные-члены, поскольку нет никакого способа определить их.
Локальный класс может обращаться далеко не ко всем именам из окружающей области видимости. Он может обращаться только к именам типов, статических переменных (см. раздел 6.1.1) и перечислений, определенных в окружающей локальной области видимости. Локальный класс не может использовать обычные локальные переменные той функции, в которой определен класс:
int a, val;
void foo(int val) {
static int si;
enum Loc { a = 1024, b }; //
struct Bar {
Loc locVal; //
int barVal;
void fooBar(Loc l = a) //
{
barVal = val; //
barVal = ::val; //
barVal = si; //
locVal = b; //
}
};
// ...
}
Содержащая функция не имеет никаких специальных прав доступа к закрытым членам локального класса. Безусловно, локальный класс вполне может сделать содержащую функцию дружественной. Как правило, локальный класс определяет свои члены как открытые. Та часть программы, которая может обращаться к локальному классу, весьма ограниченна. Локальный класс сосредоточен (инкапсулирован) в своей локальной области видимости. Дальнейшая инкапсуляция, подразумевающая сокрытие информации, безусловно, является излишней.
Поиск имен в теле локального класса осуществляется таким же образом, как и у остальных классов. Имена, используемые в объявлениях членов класса, должны быть объявлены в области видимости до их применения. Имена, используемые в определениях членов, могут располагаться в любой части области видимости локального класса. Поиск имен, не найденных среди членов класса, осуществляется сначала в содержащей локальной области видимости, а затем вне области видимости, заключающей саму функцию.
Вполне возможно вложить класс в локальный класс. В данном случае определение вложенного класса может располагаться вне тела локального класса. Однако вложенный класс следует определить в той же локальной области видимости, в которой определен локальный класс:
void foo() {
class Bar {
public:
// ...
class Nested; //
};
//
class Bar::Nested {
// ...
};
}
Как обычно, при определении члена вне класса следует указать область видимости имени. Следовательно, определение Bar::Nested
означает класс Nested
, определенный в пределах класса Bar
.
Класс, вложенный в локальный класс, сам является локальным классом, со всеми соответствующими ограничениями. Все члены вложенного класса должны быть определены в теле самого вложенного класса.
19.8. Возможности, снижающие переносимость
Для поддержки низкоуровневого программирования язык С++ определяет набор средств, применение которых снижает переносимость приложений.
В этом разделе рассматриваются два дополнительных средства, снижающих переносимость, унаследованных языком С++ от языка С: речь идет о битовых полях и спецификаторе volatile
. Также будут рассмотрены директивы компоновки, которые тоже снижают переносимость.