Программирование на C и C++

Онлайн справочник программиста на C и C++

Наследование

Наследование является одной из главных особенностей объектно-ориентированного программи­рования. В С++ наследование поддерживается за счет того, что одному классу разрешается при своем объявлении включать в себя другой класс. Наследование позволяет построить иерархию классов от более общего к более частным. Этот процесс включает в себя определение базового класса, определяющего общие качества всех объектов, которые будут выведены затем из базового класса. Базовый класс представляет собой наиболее общее описание. Выведенные из базового класса классы обычно называют производными классами. Производные классы включают в себя все черты базового класса и, кроме того, добавляют новые качества, характерные именно для данного про­изводного класса. Чтобы продемонстрировать, как работает этот процесс, в следующем примере созданы классы, классифицирующие различные типы средств передвижения.
В качестве начального рассмотрим класс, названный road_vehicle (дорожное средство передви­жения), который служит очень широким определением средств передвижения по дорогам. Он хранит информацию о числе колес движущегося средства и о числе пассажиров, которые он может вмещать:

class road_vehicle {
int wheels;
int passengers;
public:
void set_wheels(int num);
int get_wheels();
void set_pass(int num);
int get_pass();
};

Теперь можно использовать это определение дорожного средства передвижения для того, что­бы определить конкретные типы. Например, в следующем фрагменте кода определен класс truck (грузовик), используя класс road_vehicle:

class truck: public road_vehicle {
int cargo;
public:
void set_cargo(int size);
int get_cargo();
void show();
};

Обратим внимание, каким образом наследуется класс road_vehicle. Общая форма записи насле­дования имеет следующий вид

class имя_нового_класса: доступ наследуемый_класс{
//тело нового класса
}

Здесь использование доступ факультативно, но если оно используется, то должно принимать значение public или private. Пока же все наследуемые классы будут использовать спецификатор public. Он означает, что все члены класса-предшественника, имеющие спецификатор доступа public, сохраняют тот же спецификатор досту­па во всех производных классах. Поэтому в данном примере члены класса truck имеют доступ к функциям-членам класса road_vehicle так, как если бы эти функции-члены были объявлены внут­ри класса truck. Однако функции-члены класса truck не имеют доступа к частным членам класса road_vehicle.

Следующая программа иллюстрирует наследование с помощью создания двух подклассов клас­са road_vehicle: truck и automobile:

#include <iostream.h>
class road_vehicle {
int wheels;
int passengers;
public:
void set_wheels(int num);
int get_wheels ();
void set_pass(int num);
int get_pass ();
};
class truck: public road_vehicle {
int cargo;
public:
void set_cargo(int size);
int get_cargo();
void show ();
};
enum type {car, van, wagon};
class automobile: public road_vehicle {
enum type car_type;
public:
void set_type (enum type t);
enum type get_type();
void show();
};
void road_vehicle::set_wheels(int num)
{
wheels = num;
}
int road_vehicle::get_wheels()
{
return wheels;
}
void road_vehicle::set_pass(int num)
{
passengers = num;
}
int road_vehicle::get_pass()
{
return passengers;
}
void truck::set_cargo(int num)
{
cargo = num;
}
int truck::get_cargo ()
{
return cargo;
}
void truck::show ()
{
cout << "Wheels: " << get_wheels() << "\n";
cout << "Passengers: " << get_pass() << "\n";
cout << "Cargo capacity in cubic feet: " << cargo << "\n";
}
void automobile::set_type(enum type t)
{
car_type = t;
}
enum type automobile::get_type()
{
return car_type;
}
void automobile::show( )
{
cout << "Wheels: " << get_wheels() << "\n";
cout << "Passengers: " << get_pass() << "\n";
cout << "Type: ";
switch(get_type ()) {
case van: cout << "Van\n";
break;
case car; cout << "Car\n";
break;
case wagon: cout << "Wagon\n";
}
}
int main()
{
truck t1, t2;
automobile c;
t1.set_wheels (18);
t1.set_pass (2);
t1.set_cargo (3200);
t2.set_wheels (6);
t2.set_pass (3);
t2.set_cargo (1200);
t1.show ();
с.set_wheels(4);
с.set_pass(6);
с.set_type(van);
с.show();
return 0;
}

Как показывает эта программа, наибольшим достоинством наследования служит возможность создания базовой классификации, которая может быть затем включена в конкретные классы. Та­ким образом, каждый объект выражает в точности те свои черты, которые определяют его место в классификации.

Обратим внимание, что классы truck и automobile включают функции-члены с одинаковым име­нем show(), которые служат для вывода информации об объекте. Это еще один аспект полимор­физма. Поскольку каждая функция show() относится к своему собственному классу, компилятор может легко установить, какую из них вызывать в конкретной ситуации.