Освой самостоятельно С++ за 21 день.
Шрифт:
20: cout << "Frisky " << Frisky->GetAge << " years old\n";
21: Frisky->SetAge(5);
22: cout << "Frisky " << Frisky->GetAge << " years old\n";
23: delete Frisky;
24: return 0;
25: }
Результат:
Frisky 2 years old
Frisky 5 years old
Анализ: В строке 19 в области динамического обмена выделяется память для хранения экземпляра класса SimpleCat. Конструктор, вызываемый по умолчанию, присваивает
Динамическое размещение членов класса
В качестве членов класса могут выступать и указатели на объекты, размещенные в области динамического обмена. В таких случаях выделение памяти для хранения этих объектов осуществляется в конструкторе или в одном из методов класса. Освобождение памяти происходит, как правило, в деструкторе (листинг 8.7.).
Листинг 8.7. Указатели как члены класса
1: // Листинг 8.7.
2: // Указатели как члены класса
3:
4: #include <iostream.h>
5:
6: class SimpleCat
7: {
8: public:
9: SimpleCat;
10: ~SimpleCat;
11: int GetAge const { return *itsAge; }
12: void SetAge(int age) { *itsAge = age; }
13:
14: int GetWeight const { return *itsWeight; }
15: void setWeight (int weight) { *itsWeight = weight; }
16:
17: private:
18: int * itsAge:
19: int * itsWeight;
20: };
21:
22: SimpleCat::SimpleCat
23: {
24: itsAge = new int(2);
25: itsWeight = new int(5);
26: }
27:
28: SimpleCat::~SimpleCat
29: {
30: delete itsAge;
31: delete itsWeight;
32: }
33:
34: int main
35: {
36: SimpleCat *Frisky = new SimpleCat;
37: cout << "Frisky " << Frisky->GetAge << " years old\n";
38: Frisky->SetAge(5);
39: cout << "Frisky " << Frisky->GetAge << " years old\n";
40: delete Frisky;
41: return 0;
42: }
Результат:
Frisky 2 years old
Frisky 5 years old
Анализ: Объявляем класс, переменными-членами которого являются два указателя на тип int. В конструкторе класса (строки 22—26) выделяется память для хранения этих переменных, а затем им присваиваются начальные значения.
Выделенная под переменные-члены память освобождается в деструкторе (строки 28—32). После освобождения памяти в деструкторе присваивать указателям нулевые значения не имеет смысла, поскольку уничтожается и сам экземпляр класса. Такая ситуация является одним из тех случаев, когда после освобождения памяти указателю можно не присваивать значение 0.
При выполнении функции, из которой осуществляется обращение к переменным класса (в данном случае main), вы можете и не знать, каким образом выполняется это обращение. Вы лишь вызываете соответствующие методы класса (GetAge и SetAge), а все операции с памятью выполняются внутренними механизмами класса.
При уничтожении объекта Frisky (строка 40) вызывается деструктор класса SimpleCat. В деструкторе память, выделенная под члены класса, освобождается. Если один из членов класса является объектом другого определенного пользователем класса, происходит вызов деструктора этого класса.
Вопросы и ответы:Если я объявляю объекг класса, хранящийся в стеке, а этот объект, в свою очередь, имеет переменные-члены, хранящиеся в области динамического обмена, то какие части объекта будрт находиться в стеке, а какие — в области динамического обмена?
#include <iostream.h>
class SimpleCat
{
public:
SimpleCat;
~SimpleCat;
int GetAge const { return *itsAge; }
// другие методы
private:
int * itsAge;
int * itsWeight;
};
SimpleCat::SimpleCat
{
itsAge = new int(2);
itsWeight = new int(5);
}
SimpleCat::~SimpleCat
{
delete itsAge;
delete itsWeight;
}
int main
{
SimpleCat Frisky;
cout << "Frisky is " << Frisky.GetAge << " years old\n";
return 0;
}
В стеке будет находиться локальная переменная Frisky. Эта переменная содержитдва указателя, каждый из которых занимает по четыре байта стековой памяти для хранения адресов целочисленных значений, размещенных в области динамического обмена. Таким образом, объект Frisky займет восемь байтов стековой памяти и восемь— в области динамического обмена.
Конечно, для данного примера динамическое размещение в памяти переменных- членов не обязательно. Однако в реальных программах такой способ хранения данных может оказаться достаточно эффективным.