ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 13.12.2020
Просмотров: 4305
Скачиваний: 28
Глава 16. Перегрузка операторов
221
class Demo
{
public:
static void* p;
void *operator new(size_t n);
void operator delete(void*);
};
void *Demo::operator new(size_t n)
{
if (p)
return p;
else
{
p = malloc(n);
return p;
}
}
void Demo::operator delete(void*)
{
if (p)
{
free(p);
p = NULL;
}
}
void* Demo::p = NULL;
int main()
{
Demo *d;
cout << !Demo::p << endl; // 1
d = new Demo();
cout << !Demo::p << endl; // 0
d = new Demo();
cout << !Demo::p << endl; // 0
delete d;
cout << !Demo::p << endl; // 1
return 0;
}
Г Л А В А
17
Наследование классов
17.1. Определение наследования
Наследование
— это отношение между классами, которое позво-
ляет классу потомку использовать члены одного или нескольких
классов предков. В языке программирования С++ класс потомок
называется
производным
(derived)
классом
от наследуемых клас-
сов, а классы предки называются
базовыми классами
. Из опреде-
ления наследования видно, что оно решает задачу повторного
использования кода. В производном классе нет необходимости
заново определять атрибуты и методы, которые наследуются им
от базового класса. Синтаксически наследование между двумя
классами определяется следующим образом:
class имя_производного_класса: public имя_базового_класса
{
// тело производного класса
};
При таком наследовании в производном классе возможен доступ
к членам базового класса, которые объявлены в разделах
public
и
protected
базового класса. В производном классе запрещен дос-
туп к членам базового класса, которые объявлены в разделе
private
базового класса.
В листинге 17.1 приведен пример определения наследования
классов и доступа к членам базового класса через объект произ-
водного класса.
Глава 17. Наследование классов
223
Листинг 17.1. Наследование классов
#include <iostream>
using namespace std;
class Base
{
int n;
public:
Base(): n(0) {}
int inc() { return ++n; }
};
class Derived: public Base
{
public:
int _inc() { return inc(); }
};
int main()
{
Derived d;
cout << d.inc() << endl; // печатает: 1
cout << d._inc() << endl; // печатает: 2
return 0;
}
Так как производный класс содержит члены базового класса, то
естественно допустить использование объектов производного
класса там, где требуются объекты базового класса. В языке про-
граммирования C++ это обеспечивается тем, что указатель и
ссылка на базовый класс совместимы по типам соответственно с
указателем и ссылкой на производный класс.
В листинге 17.2 приведен пример использования объектов произ-
водного класса вместо объектов базового класса через указатели
и ссылки на базовый класс.
Часть II. Язык программирования С++
224
Листинг 17.2. Использование объектов производного класса
через указатели и ссылки на объекты базового класса
#include <iostream>
using namespace std;
class Base
{
public:
int one() { return 1; }
};
class Derived: public Base
{
public:
int two() { return 2; }
};
int foo(Base* b) { return b->one(); }
int foo(Base& b) { return b.one(); }
int main()
{
Derived d;
cout << foo(&d) << ' ' << foo(d) << endl; // печатает: 1 1
return 0;
}
Если атрибут или метод производного класса имеет такое же имя,
как соответственно атрибут или метод базового класса, то этот
член производного класса
скрывает
(hides) соответствующий
член базового класса. В этом случае для доступа к скрытому чле-
ну базового класса нужно использовать оператор разрешения об-
ласти видимости с именем базового класса.
В листинге 17.3 приведен пример доступа к скрытым членам ба-
зового класса.
Листинг 17.3. Доступ к скрытым членам базового класса
#include <iostream>
using namespace std;
Глава 17. Наследование классов
225
class Base
{
public:
int what() { return 10; }
};
class Derived: public Base
{
public:
int what() { return 20; }
};
int main()
{
Derived d;
cout << d.Base::what() << endl; // 10
cout << d.what() << endl; // 20
return 0;
}
17.2. Доступ к членам, наследуемым
от базового класса
При определении производного класса можно также определить
права доступа к членам, наследуемым от базового класса. Для
этого в определении производного класса перед именем базового
класса записывается один из спецификаторов доступа
public
,
protected
или
private
.
Если класс наследуется как
public
, то права доступа к
public
и
protected
членам, наследуемым от базового класса, в производ-
ном классе не изменяются.
Если класс наследуется как
protected
, то все
public
и
protected
члены базового класса становятся
protected
членами производ-
ного класса.
Если класс наследуется как
private
, то все
public
и
protected
члены, наследуемые от базового класса, становятся
private
чле-
нами производного класса.