
- •Int count;
- •Void SetCount ( int n)
- •Int GetCount(void)
- •Void changCount(int n)
- •Void ChangeCount(int n)
- •Int secondCount;
- •Void ChangCount(int n)
- •Int count;
- •Void fa(void);
- •Void fв(void);
- •Void fc(void);
- •Void f (void);
- •Void g(void);
- •Void Display(void)
- •Void Display(void)
- •Void Display(void);
- •Void tState::Display(void)
- •Void Display(void);
- •Void Display(void);
- •Void tPopulation::Display(void)
- •Наследуемые производным классом
- •Virtual void vf();
- •Virtual void vf();
- •Virtual void vf();
- •Virtual void Draw();
- •Virtual void Draw();
- •Virtual void Draw();
- •Int value;
- •Int GetValue(void) {return value; }
- •Int multiplier ;
- •Int GetValue(void) {return value *multiplier; }
- •Virtual void f1(void);
- •Void AbstractClass::f1(void)
- •Void MyClass::f2(void)
- •5://Неполные объявления класса
- •6: Class tElem ;
Void Display(void)
{ cout << ”x = = ” << x << ‘\n’ ; }
};
Допустим: класс В наследует А в качестве закрытого базового класса:
class B: private A {
public:
B(): A() {cout <<
“Inside B’s constructor\n”; }
};
Т.к. класс А - закрытый в B, все прежде открытые в А члены теперь закрытые в B, след-но, во всех последующих производных от В классах или внешних по отношению к В операторах нельзя вызвать функцию-член Display(), наследованную из класса А.
пример
//выполняется правильно:
A objectA;
objectA.Display();
// Display() недоступна).
B objectB;
objectB.Display();
// ???? Display() закрыта в B
можно выборочно квалифицировать один или несколько из наследуемых членов
ПРИмер
Если вы хотите сделать закрытыми в производном классе только некоторые из наследуемых членов, можно выборочно квалифицировать один или несколько из них. Предположим, вы хотите, чтобы открытый в А целочисленный член x стал закрытым в B, а открытая в А функция Display() осталось бы открытой в B так, чтобы внешние операторы могли ее вызывать. Для этого укажите базовый класс А закрытым в B, как это уже делалось ранее, а в открытой секции В квалифицируйте наследуемые члены, которые вы хотели бы оставит открытыми:
//открытый в А член x стал закрытым в B
//открытая в А ф-ция Display() //осталось открытой в B
class B: private A {
public:
A::Display;
// Выборочно уточнение Display()
// Display() осталась открытой
//x станет закрытым членом класса В
B(): A() { cout <<
”Inside B’s constructor\n”; }
};
Выражение А::Display; в открытой секции класса В указывает компилятору, что этот член, объявленный в классе А, должен остаться открытым. Наследуемый целочисленный член x станет закрытым членом класса В, как и прежде, однако функция-член Display() останется открытой. Предыдущая попытка вызова Display() для объекта класса В теперь скомпилируется и выполнится правильно:
//Теперь правильно!
B objectB;
objectB.Display();
// Display() – открытый член B
Использование конструкторов и деструкторов
в производном классе обычно необходим конструктор, если он определен и в базовом классе
конструктор базового класса должен вызываться, чтобы инициализировать все данные-члены в базовых классах.
В производном классе деструктор нужен только при наличии членов, которые необходимо удалять
ПРИМЕР базового класса
class TBase {
private:
//указатель basep на строку символов
char *basep;
public:
//создание копии строкового
//аргумента в виде динамической
// переменной с присвоением адреса
// выделенной памяти указателю basep.
TBase(const char *s)
{ basep = strdup(s); }
TBase() { delete basep; }
const char *GetStr(void)
{ return basep; }
};
Класс TBase имеет один защищенный член – указатель basep на строку символов. Конструктор класса вызывает библиотечную функцию strdup() для создания копии строкового аргумента в виде динамической переменной с присвоением адреса выделенной памяти указателю basep. Деструктор-TBase() освобождают этот блок памяти, когда объект типа TBase выходит из области видимости. При создании объекта типа:
// создание объекта
TBase president(“George Washington”);
//конструктору класса передается //строка “ George Washington ”
//создание копии строки и //присваивание ее адреса члену basep //объекта president
//Для отображения строки, //хранящейся в president
cout << president. GetStr();
Когда president выходит из области видимости, деструктор класса удаляет строку, хранящуюся в куче.
Рис. 3.7. иллюстрирует предоставление president в памяти.
Рис.3.7. Представление объекта
типа TBase в памяти
Рассмотрим, что происходит в новом классе, производном от TBase. Производный класс можно объявить следующим образом:
ПРИМЕР производного класса
class TD: public TBase {
private:
// символьный указатель,
//ссылающийся на копию строки,
// хранящейся в TBase,
//с символами, преобразованными
//в прописные
char *up;
public:
TD(const char *s);
TD() { delete up; }
const char *GetUStr(void)
{return up; }
};
//Конструктор TDerived
TD::TD(const char *s)
: TBase(s)
// Вызов конструкторов базового
//класса
{
up = strupr(strdup(s));
// Инициализация данных TDerived
};
Конструктор TD вызывает конструктора TBase, копирующий строку, на которую ссылается s, в кучу и инициализирующий указатель basep адресом копии строки. По завершении этой операции конструктор производного класса создает еще одну копию строки, преобразуя ее символы в прописные буквы путем обращения к библиотечной функции strupr(), и присваивает up адрес этой копи строки.
При создании объекта типа TD, создается две копии строки: одну неизмененную и одну, символы которой преобразованы в прописные.
//ПРИМЕР
TD president(
“George Washington”);
// выполнить следующие операторы:
cout << “Original string: ”
<<president.GetStr() << ‘\n’;
cout << “Up string: ”
<<president.GetUStr() << ‘\n’;
//на экране
Original string: George Washington
Uppercase string: GEORGE WASHINGTON
Первый оператор вывода отображает первоначальную неизмененную копию строки: “George Washington”. Второй – копию этой же строки, все буквы который преобразованы в прописные, инициализированную конструктором производного класса:
Original string: George Washington
Uppercase string: GEORGE WASHINGTON
Рис. 3.8. иллюстрирует
представление объекта класса
president в памяти.
Рис.3.8. Представление объекта типа
TD в памяти
Объект производного класса, подобный president, должен аккуратно освобождать все выделенные участки памяти. На рис. 3.8. объекту классу president принадлежит два блока памяти. Когда объект выходит из области видимости, его деструктор освобождает эту память и возвращает ее куче для последующего использования.
Деструктор класса TBase освобождает память, на которую ссылается член basep. Для простоты деструктор объявлен встраиваемым:
TBase() {delete basep; }
Аналогично, деструктор TDerived освобождает память, на которую ссылается член uppercasep. Опять же, объявление деструктора встраиваемым позволяет упростить код:
TDerived() { delete uppercasep; }
В отличие от конструкторов, деструктор производного класса никогда не вызывает непосредственно деструктор базового класса.
С++ автоматически вызывает деструкторы, когда объекты класса выходят из области видимости.
Например при выходе объект класса president из области видимости С++ сначала вызывает деструктор производного класса, выполняющего следующий оператор:
delete up;
Затем С++ вызывает деструктора базового класса, выполняющий оператор:
delete basep;
Т.о., две строки удаляются а порядке, обратном порядку их создания.
Самый простой способ запоминания порядка вызова конструкторов и деструкторов – представление иерархии базовых и производных классов в виде многоэтажного задания. Конструкторы базовых классов вызываются перед конструкторами производных классов, конструируя таким образом производные объекты снизу вверх, подобно тому, как небоскреб возводится ввысь от фундамента к крыше. Когда объект производного класса выходит из области видимости, его деструкторы вызываются в обратном порядке, разрушая объект по частям путем вызова деструкторов производных классов перед деструкторами базовых классов, подобно тому, как разрушают реальное задание от крыши до фундамента.
@@@@@@@@@@
Использование замещающих функций-членов
В производном классе обычно добавляются новые данные и функции-члены. Однако существует также возможность замещения функций-членов, наследованных из базового класса.
//ПРИМЕР
class TBase {
private:
char *sptr;
public:
TBase(const char *s)
{sptr = strdup(s); }
TBase() {delete sptr; }