Доступ к членам и наследование
Стр 1 из 3Следующая ⇒ Лабораторная работа 6. Наследование Цели, достигаемые в этой работе
1. Познакомиться с основами наследования 2. Понять, как производные классы наследуют от базовых 3. Освоить вызов конструкторов базовых классов 4. Научиться создавать многоуровневую иерархическую структуру классов 5. Познакомиться со случаями наследования от нескольких базовых классов 6. Узнать, когда вызываются конструкторы и деструкторы, входящие в иерархию классов
Основы наследования
Наследование — это средство, позволяющее одному классу наследовать характеристики другого. Согласно языку С++, наследуемый класс называется базовым классом. Класс, который наследует от базового, называется производным классом. Производный класс наследует все члены, определенные в базовом классе, и добавляет к ним свои собственные специфические элементы. В С++ наследование реализуется путем включения одного класса (базового) в объявление другого (производного). Другими словами, в объявлении производного класса указывается, какой класс является для него базовым. Общая форма наследования приведена ниже:
class производный-класс: сп_доступа базовый-класс { тело производного класса } Здесь сп_доступа – одно из ключевых слов public, private или protected. Если член класса объявлен как public, к нему можно обратиться из любого места в программе. Если член объявлен как private, он доступен только членам своего класса. При этом производные классы не имеют доступа к членам private базового класса. Если член объявлен как protected, он доступен только членам своего класса и производных классов. Таким образом, атрибут protected позволяет члену наследоваться, но оставаться закрытым внутри иерархии классов.
Если базовый класс наследуется с атрибутом public, его открытые члены становятся открытыми членами производного класса, а его защищенные члены становятся защищенными членами производного класса. Если базовый класс наследуется с атрибутом protected, его открытые и защищенные члены становятся защищенными членами производного класса. Если базовый класс наследуется с атрибутом private, его открытые и защищенные члены становятся закрытыми членами производного класса Во всех случаях закрытые члены базового класса остаются закрытыми в этом классе.
Примеры
1. Рассмотрим простой пример, иллюстрирующий некоторые ключевые черты наследования. Приведенная ниже программа создает базовый класс TwoDShape (двумерная фигура), который содержит ширину и высоту двумерного объекта, а также производный класс Triangle (треугольник). Обратите особое внимание на способ объявления класса Triangle
// Lab_3_Nasl1.cpp: Defines the entry point for the console application. // // Простая иерархия классов.
#include "stdafx.h" #include <iostream> #include <cstring> #include <conio.h> using namespace std;
// Класс для двумерных объектов. class TwoDShape { public: double width; double height; void showDim() { cout << "width and height are " << width << " и " << height << "\n"; } };
//Triangle является производным от TwoDShape. class Triangle: public TwoDShape { public: char style [20]; double area() { //Triangle может работать с членами TwoDShape, как return width * height / 2; // если бы они были его собственными. } void showStyle() { cout << "Triangle " << style << "\n"; } };
int main() { Triangle t1; Triangle t2; //Все члены Triangle доступны объектам Triangle, даже те, которые //наследованы от TwoDShape. t1.width = 4.0; t1. height = 4.0; strcpy_s (t1. style, "isosceles");//равнобедренний
t2.width = 8.0; t2.height = 12.0; strcpy_s(t2.style, "rectangular ");//прямоугольный
cout << "Data of о tl:\n"; t1.showStyle (); t1.showDim(); cout << "Area equal " << t1.area() << "\n"; cout << " \n";
cout << "Data of о t2:\n"; t2.showStyle(); t2.showDim(); cout << "Area equal " << t2.area() << "\n-"; _getch(); return 0; }
Вывод этой программы выглядит следующим образом:
В этой программе TwoDShape определяет атрибуты "обобщенной" двумерной фигуры, например, квадрата, прямоугольника, треугольника и т.д. Класс Triangle создает специфический тип класса TwoDShape, в данном случае треугольник. Класс Triangle включает все члены TwoDShape и добавляет поле style, функцию агеа() и функцию showStyle(). Описание вида треугольника хранится в поле style, агеа() вычисляет и возвращает площадь треугольника, a showStyle() выводит на экран вид треугольника. Следующая строка показывает, как Triangle наследует от TwoDShape:
class Triangle: public TwoDShape {
Здесь TwoDShape - это базовый класс; от него наследует класс Triangle, являющийся производным классом. Поскольку Triangle наследует все члены своего базового класса TwoDShape, он может внутри функции агеа() обращаться к переменным width и height. Кроме того, внутри main() объекты t1 и t2 могут обращаться к width и height непосредственно, как если бы они были частью Triangle. На рис. 10-1 схематически показано, как класс TwoDShape входит в Triangle. Еще одно замечание: хотя TwoDShape является базовым для Triangle, он также является полностью независимым, самостоятельным классом. То, что некоторый класс является базовым для производного класса, никак не значит, что он не может быть использован сам по себе.
2. Основное преимущество наследования заключается в возможности, после того, как вы создали базовый класс, определяющий общие характеристики группы объектов, использовать его для создания любого числа более специфических производных классов. Каждый производный класс может детально определить собственные средства. Вот пример другого класса, наследуемого от того же TwoDShape, который инкапсулирует прямоугольники:
// Производный от TwoDShape класс для прямоугольников. class Rectangle: public TwoDShape {
public: bool isSquare() { if(width == height) return true; return false; }
double area() { return width * height; } };
Класс Rectangle включает все содержимое TwoDShape и добавляет функцию isSquare(), которая определяет, не является ли прямоугольник квадратом, а также функцию агеа() для вычисления площади прямоугольника.
Доступ к членам и наследование
Как вы уже знаете, члены класса часто объявляются закрытыми, чтобы предотвратить неавторизованный доступ или неразумное использование. Наследование от класса не нарушает ограничение доступа к закрытым членам. Таким образом, хотя производный класс включает все члены базового, он не может обратиться к закрытым членам базового класса. Например, если переменные width и heigh t объявить в классе TwoDShape закрытыми, как это показано ниже, тогда Triangle не будет иметь к ним доступа.
/* Производным классам закрыт доступ к закрытым членам базового класса. */ class TwoDShape { double width; double height; public: void showDim () { cout << "Ширина и высота составляют " << width << " и " << height << "\n"; } };
// Triangle является производным от TwoDShape. class Triangle: public TwoDShape { public: char style [20]; double area () { //К закрытым членам базового класса обращаться нельзя return width * height /2; // Ошибка! Доступ закрыт. } void showStyle () { cout << "Треугольник " << style << "\n"; } };
Класс Triangle не будет компилироваться, потому что обращение к width и heigh t внутри функции агеа() приведет к нарушению доступа. Поскольку width и height теперь закрыты, к ним можно обратиться только из членов их собственного класса. Производные классы доступа к ним не имеют. Доступ к закрытым членам базового класса из производных классов заключается в использовании открытых функций для обеспечения доступа к закрытым данным. Как вы уже знаете, обычно доступ к закрытым членам класса осуществляется посредством функций доступа. Ниже приведен новый вариант класса TwoDShape, в который добавлены функции доступа для переменных width и height:
//Обращение к закрытым данным посредством функций доступа.
#include "stdafx.h" #include <iostream> #include <cstring> #include <conio.h> using namespace std;
//Клacc для двумерных объектов, class TwoDShape { //эти члены закрыты double width; double height; public: void showDim() { cout << "width and height are " << width << " и " << height << "\n"; }
// функции доступа для width и height. double getWidth() { return width; } double getHeight () { return height; } void setWidth(double w) { width = w; }
void setHeight (double h) { height = h; } };
// Triangle является производным от TwoDShape. class Triangle: public TwoDShape { public: char style [20]; //Использование функции доступа для получения ширины и высоты. double area () { return getWidth () * getHeight () / 2; }
void showStyle () { cout << "Triangle " << style << "\n"; } }; int main () { Triangle t1; Triangle t2; t1.setWidth(4.0); t1.setHeight(4.0); strcpy_s (t1. style, "isosceles ");//равнобедренный t2.setWidth(8.0); t2.setHeight(12.0); strcpy_s(t2.style, "rectangular ");//прямоугольный
cout << "Data of о t1:\n"; t1.showStyle(); t1.showDim(); cout << "Area equal " << t1.area() << "\n";
cout << "\n"; cout << "Data of о t2:\n"; t2.showStyle (); t2. showDim (); cout << "Area equal " << t2.area() << "\n"; _getch(); return 0; }
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|