Для работы со статическими элементами данных создаются статические элементы-функции. Их оглавления имеют вид:
static тип_результата имя_функции (параметры).
Параметры – только статические элементы данных.
Статическая элемент-функция существует в одном экземпляре. Создается и может быть вызвана даже в том случае, когда не существует ни одного объекта данного класса. Она не ассоциируется с отдельными объектами класса, потому при ее вызове не передается указатель this.
Статическая функция может вызывать только другие статические
функции-элементы данного класса. Не может быть виртуальной. Вызов статической функции имеет вид:
имя_класса:: имя_функции (фактические параметры);
Пример 1 Демонстрирует факт возможности вызова статической функции_элемента даже при отсутствии объектов данного класса.
# include <stdio. h >
class A
{
public:
static void stat_func ()
{
puts (“ Я существую сама по себе!”);
}
};
void main ()
{
A:: static_func (); // Вызов статической функции.
}
Пример 2 Демонстрирует особенности обработки статических и нестатических элементов данных статическими и нестатическими функциями – членами класса.
#include<stdio.h>
class coord
{
static float x;
float y;
public:
coord(float a):y(a)
{
}
static void f_stat()
{
puts(“Введите х=”);
scanf(“%f”,&x”);
printf(“x=%f\n”,x);
}
void f_non _stat()
{
puts(“Введите х=”);
scanf(“%f”,&x”);
printf(“x=%f y=%f\n”,x,y);
}
}
float coord::x=12.5;//Инициализация х.
void main()
{
coord w(45);// w.x=12.5;w.y=45.
w.f_stat();//Можно, но через this ничего //не передается.
w.f_non_stat();
coord::f_stat();//Еще один способ//вызова статической функции.
}
В этом примере приведен конструктор инициализации. Он может инициализировать только нестатический элемент данных y. Статическая функция-элемент f_stat() обрабатывает статический элемент данных x. При попытке ввода нестатического элемента данных y его значение не изменится. Статическая функция-элемент не обрабатывает нестатические элементы данных. Зато нестатическая функция-элемент f_non_stat() может осуществлять ввод статического элемента данных x. Если при описании класса приведен прототип статической функции – члена, а сама функция определена позже, то ключевое слово static следует ставить только перед прототипом.
Константные объекты и константные элементы- функции
Ранее были рассмотрены const элементы-данные. Для их инициализации в конструкторе употреблялся список инициализации. Например:
Class coord
{
Const int x, y;
public:
coord (int a, int b): x(a), y(b)
{
}
};
Сейчас речь пойдет не об элементах-данных, а о константных объектах и константных элементах-функциях.
Константные объекты нужны в тех случаях, когда их применяют только для чтения. Изменять их значения нельзя принципиально. И чтобы не сделать это в программе случайно, для работы с константными объектами применяют константные функции-элементы. Эти функции не могут реализовать операцию присваивания элементам-данным константных объектов новых значений. Поэтому константные объекты могут работать (вызывать, связываться) только с константными элементами-функциями. Хотя сами константные функции могут вызываться и неконстантными объектами.
Перед константным объектом пишется ключевое слово сonst. Например:
Class A
{
===========
};
Void main ()
{
const A w; // w -константный объект
}
Константная функция-элемент выглядит так:
Class A
{
===========
public:
Тип_результата имя_функции (параметры) const
{
===========
}
};
Пример.
# include <stdio.h>
Class A
{
Int x, y;
public:
A ()
{
}
A (int a, int b)
{
x=a;
y=b;
}
// Сейчас будет попытка выполнить недопустимое присвоение в
// константной функции
Void p_const () const
{
x=12; // Cannot modify a const object
y=15; // Cannot modify a const object
}
// Далее эти же действия выполняет неконстантная функция
Void p_non_const ()
{
x=12;
y=15;
}
};
Void main ()
{
const A w (1,2); // w -константный объект
A q; // q -неконстантный объект
w.p_const (); // Разрешается
q.p_const (); // Разрешается
w.p_non_const (); // Warning: non-const
// function A::p_non_const () called for
// const object. Это сообщение будет независимо от того
// есть ли недопустимое присвоение в p_non_const () или нет.
}
Внимание! Константная функция не может включать операцию присвоения для элементов-данных. Нельзя присвоить х=12; у=15, как это показано в примере. Но обнаруживается, что компилятор “не замечает”, если в константной функции ввести новые значения элементов-данных для константного объекта. Так, например, в константной функции p_const () можно сделать так:
Void p_const () const
{
puts (“Введите х, в”);
scanf (“%i%i”, &x, &y);
}
Лекция 22
Наследование классов
Нередко несколько классов могут иметь одинаковые элементы данных. Например, class student, class teacher, class officer должны иметь такие элементы-данные, как имя, адрес, возраст. В этом случае удобно сделать т.н. базовый класс class man, у которого будут перечисленные общие для нескольких классов элементы данных, а также необходимые члены-функции. А у этого базового класса будут производные от него классы: class student, class teacher, class officer. Эти классы будут использовать элементы базового класса и, кроме этого, иметь свои собственные элементы данных и элементы-функции.
Имеет место т.н. наследование классов. Причем производные классы, в свою очередь, могут быть базовыми для других производных от них классов. Синтаксис наследования имеет следующий вид:
сlass Base
{
.
.
.
};
сlass Derived: ключ_доступа Base
{
.
.
.
};
Ключ_доступа не является обязательным и может быть private, protected или public. Если он не указан, то по умолчанию принимается private для классов и public для структур.
Ключ_доступа определяет уровень доступа к элементам базового класса. Ниже приводится таблица с вариантами доступа.
Ключ_доступа | Доступ в базовом классе | Доступ в производном классе |
public | рublic рrotected private | рublic рrotected private |
protected | рublic рrotected private | рrotected рrotected private |
private | рublic рrotected private | рrivate рrivate рrivate |
В последнем случае имеет место доступ лишь к членам-функциям базового класса (если они в области действия метки доступа рublic).
Наследование бывает простым и множественным. Простым наследованием называется случай, когда производный класс имеет всего один базовый класс. При множественном наследии класс является производным от нескольких базовых классов.
Пример.
сlass А
{
.
.
. };
сlass В
{
..
.
};
сlass С: рublic А, рublic В
{
.
.
};
Здесь класс С является производным от базовых для него классов А и В. Рассмотрим пример простого наследования. Базовый – class man. Производный – сlass student. Напомним, что метка доступа рrotected в базовом классе позволяет иметь доступ из производного класса к элементам базового, находящимся в области действия этой метки.
#include<stdio.h>
class man
{
рrotected:
char* name;//имя
char*address;//адрес
int age;//возраст
рublic:
void get_man_info()
{
name=new char[15];
address=new char[20];
puts(“Введите имя”);
fflush(stdin);
scanf(“%s”,name);
puts(“Введите адрес”);
fflush(stdin);
scanf(“%s”, address);
puts(“Введите возраст”);
scanf(“%i”, &age);
}
void put_man_info()
{
printf(“Имя человека %s.Его адрес % s. Возраст %i\n”,name,address,age);
}
}: //Закончилось описание класса man
class student:public man
{
char* group; //группа
рublic:
void get_stud_info()
{
group =new char[10];
puts(“Введите группу”);
fflush(stdin);
scanf(“%i”, group);
}
void put_stud_info()
{
printf(“Имя студента %s.Его адрес % s. возраст. Учится в группе % s \n”,name,address,age, group);// Используются элементы-данные из базового класса.
}
}
void main
{
man x;//Элемент базового класса
x.get_man_info();
x.put_man_info();
student y; //Элемент производного класса
y.get_man_info();
y.get_stud_info();
y.put_stud_info();
}
Здесь объект производного класса y вызывает функцию get_man_info(), являющуюся членом-функцией базового класса man. При вызове y.put_stud_info() будут выведены y.name, y.address, y.age и y.group.
В принципе, class student мог бы быть базовым, например, для class stud_sport (студент-спортсмен). Для этого в class student метку доступа к элементу данных group нужно сделать рrotected. Тогда объекты класса stud_sport смогут использовать элементы-данные и члены-функции как класса student, так и класса man, являющегося базовым для класса student.