Локальные и вложенные классы
В С++ поддерживается 2 области видимости: области видимости файла, локальная область видимости и область видимости класса. В то же время класс может быть определен внутри некоторого блока или функции, т.е. иметь локальную область видимости. В этом случае имя класса видно только в этой локальной области видимости.
void f()
{
//...
class X
{
...
}
X s2;
}
X s3; //ошибка
Локальное описание класса видно только в той области видимости, в которой этот класс описан.
void f2()//локальные переменные блока, в котором описан класса не видим
{ double x,y;
class X
{
...//x,y не видимы
}
]
Все методы локального класса должны быть встраиваемые.
Вложенность
Класс можно определить внутри другого класса. В этом случае внутренний класс называется вложенным. Современный стандарт С++ распространяет спецификацию доступа не только на данные, но и на имена вложенных классов. Области видимости и вложенность позволяет локально скрывать имена и выделять ресурсы. Очень часто бывает такая ситуация, что класс нужен как часть реализации некой большей конструкции.
Приведем программу, в которой реализуется класс, реализующий стек указателей на строки. Вложенные классы – указатели на стек.
class StrStack
{
class Link
{
class xste;
Link *next;
public:
Link(char *.ste,Link *_next):str(_str),next(_next)
{}//список инициализации
char * GetStr();//описание находится вне класса
Link *GetNext {return next;}
};
Link *head;
public:
StrSrack():head(0){}
~StrStack();
void Add(char *s);
char* Get();
int Empty() const {return !head;}
StrStack &operator+(char *str)
{
Add(str);
return *this;
}
};
//описание методов
inline char* StrStack::Link::GetStr()
{
return str;
}
//описание методов внешнего класса
StrStack::~StrStack()
{
while(!Empty())
{
Get();
}
}
void StrStack:: Add(char *str)
{
Link *p=new Link(str,head);
head =p;
}
char *StrStack:: Get()
{
if(!head) return “Пустой стек”;
char *str=head->getstr();
Link *p=head;
head=head->getnext();
delete p;
}
////
void main()
{
StrStack s;
s.Add(“Маша”);
s.Add(“Саша”);
s+”Даша”-“Паша”;
...
while(!s.Empty())
return s.get();
}
Специальный вид методов класса - конструкторы и деструкторы.
Конструкторы предназначены для инициализации объектов. Допускается наличие нескольких конструкторов. Они не имеют возвращаемого значения. Конструкторы имеются у любого класса, даже если они не определены.
class Y
{
public:
int x,y;
};
У такого класса имеется 2 конструктора: конструктор по умолчанию, который не имеет параметров и мог бы быть описан как Y::Y(){}. Второй конструктор называется конструктором копий и мог бы быть описан в определении класса следующим образом: Y (const &y); . Он используется при создании объекта с инициализацией объекта того же типа. Кроме того конструктор копий используется при инициализации формального параметра функции в случае передачи ей объекта по значению, а так же при возврате из функции по оператору return.
При передачи ссылок и указателей конструктор копий не используется. Только когда речь идет возврате и передачи по значению. Неявный конструктор копий обеспечивает простое копирование одного объекта во второй. Такое копирование называется поверхностным (shallow copy).
При явном написании хотя бы одного конструктора (в том числе и конструктора копий) конструктор по умолчанию перестает существовать. Однако неявный конструктор копий остается, и по-прежнему будет осуществлять поверхностное копирование объектов при инициализации. Если конструктор копий описан явно, то перестает существовать и неявный конструктор копий по умолчанию.
Конструктор копирования-это специальное вид конструктора, получающий в качестве единственного параметра ссылку на объект этого же класса
Конструктор по умолчанию-это конструктор, вызывающийся без параметров
Деструкор-это особый вид метода, применяющийся для освобождения памяти