If константное выражение группа операций #elif константное выражение группа операций #else группа операций #endif
Отличие директив #ifdef/#ifndef заключается в том, что константное выражение может быть задано только с помощью #define.
У каждой директивы #if в исходном файле должна быть соответствующая закрывающая директива #endif. Между директивами #if и #endif может располагаться любое количество директив #elif, однако допускается не более одной директивы #else. Директива #else, если присутствует, должна быть последней перед директивой #endif.
Пример
#include <stdio.h>
#include <stdlib.h>
#define P 2
int main() {
system("chcp 1251");
system("cls");
#if P==1
printf("Выполняется ветка 1");
#elif P==2
printf("Выполняется ветка 2, P=%d", P);
#else
printf("Выполняется другая ветка, P=%d", P);
#endif
getchar();
return 0;
}
Результат выполнения
Вопрос 2:Управление доступом к членам базового класса в C++.Наследование. Примеры
1) Управление доступом к членам базового класса в C++
· Управление доступом к членам
Тип доступа | Назначение |
private | Члены классов, объявленные как private может использоваться только функции-членами и другами (классы) класса или функции. |
protected | Члены классов, объявленные как protected может использоваться функции-членами и другами (классы) класса или функции. Кроме того, они могут быть использованы классами, унаследованными от класса. |
public | Члены классов, объявленные как Открытый может использоваться любой функцией. |
· Справки управления доступом не позволяют избежать использования объектов в целях они не были предназначены для использования.Данная защита будут потеряны, если явные преобразования типов (cast) выполняются.
![]() |
Управление доступом одинаково применимо ко всем именам: функции-члены, данные элемента, вложенные классы и перечислителей. |
· По умолчанию доступ к членам класса (членам типа, объявленного с помощью класса класс ключевое слово) private; по умолчанию доступ кstruct и union члены являются открытыми. В любом случае текущий уровень доступа можно изменить с помощью Открытый" privateилиprotected ключевое слово.
2)Наследование
Наследование — это механизм создания нового класса на основе уже существующего. При этом к существующему классу могут быть добавлены новые элементы (данные и функции), либо существующие функции могут быть изменены. Основное назначение механизма наследования — повторное использование кодов, так как большинство используемых типов данных являются вариантами друг друга, и писать для каждого свой класс нецелесообразно.
Объекты разных классов и сами классы могут находиться в отношении наследования, при котором формируется иерархия объектов, соответствующая заранее предусмотренной иерархии классов.
Иерархия классов позволяет определять новые классы на основе уже имеющихся. Имеющиеся классы обычно называют базовыми(иногда порождающими), а новые классы, формируемые на основе базовых, – производными (порожденными, классами-потомками или наследниками).
Производные классы «получают наследство» – данные и методы своих базовых классов, и могут пополняться собственными компонентами (данными и собственными методами). Наследуемые компоненты не перемещаются в производный класс, а остаются в базовых классах. Сообщение, обработку которого не могут выполнить методы производного класса, автоматически передается в базовый класс. Если для обработки сообщения нужны данные, отсутствующие в производном классе, то их пытаются отыскать автоматически в базовом классе.
При наследовании некоторые имена методов (функций-членов) и данных-членов базового класса могут быть по-новому определены в производном классе. В этом случае соответствующие компоненты базового класса становятся недоступными из производного класса. Для доступа из производного класса к компонентам базового класса, имена которых повторно определены в производном, используется операция разрешения контекста ::
Для порождения нового класса на основе существующего используется следующая общая форма
сlass Имя : МодификаторДоступа ИмяБазовогоКласса
{ объявление_членов;};
При объявлении порождаемого класса МодификаторДоступа может принимать значения public, private, protected либо отсутствовать, по умолчанию используется значение private. В любом случае порожденный класс наследует все члены базового класса, но доступ имеет не ко всем. Ему доступны общие (public) члены базового класса и недоступны частные (private).
Для того, чтобы порожденный класс имел доступ к некоторым скрытым членам базового класса, в базовом классе их необходимо объявить со спецификацией доступа защищенные (protected). Члены класса с доступом protected видимы в пределах класса и в любом классе, порожденном из этого класса.
Общее наследование
При общем наследовании порожденный класс имеет доступ к наследуемым членам базового класса с видимостью public и protected. Члены базового класса с видимостью private – недоступны.
Спецификация доступа | внутри класса | в порожденном классе | вне класса |
private | + | - | - |
protected | + | + | - |
public | + | + | + |
Общее наследование означает, что порожденный класс – это подтип базового класса. Таким образом, порожденный класс представляет собой модификацию базового класса, которая наследует общие и защищенные члены базового класса.
Пример
class student {
protected:
char fac[20];
char spec[30];
char name[15];
public:
student(char *f, char *s, char *n);
void print();
};
class grad_student : public student {
protected:
int year;
char work[30];
public:
grad_student(char *f, char *s, char *n, char *w, int y);
void print();
};
Порожденный класс наследует все данные класса student, имеет доступ к protected и public-членам базового класса. В новом классе добавлено два член-данных, и порожденный класс переопределяет функцию print().
student :: student(char *f, char *s, char *n) {
strcpy(fac, f);
strcpy(spec, s);
strcpy(name, n);
}
grad_student :: grad_student(char *f, char *s, char *n, char *w, int y) :
student(f,s,n) {
year = y;
strcpy(work, w);
}
Конструктор для базового класса вызывается в списке инициализации.
Перегрузка функции print().
void student :: print() {
cout << endl << "fac: " << fac << " spec: " << spec
<< " name: " << name;
}
void grad_student :: print() {
student :: print();
cout << " work: " << work << " year: " << year;
}
int main() {
system("chcp 1251");
system("cls");
student s("МТ", "АМСП", "Сидоров Иван");
grad_student stud("ПС", "УиТС", "Иванов Петр", "Метран", 2000);
student *p = &s;
p->print();
grad_student *gs = &stud;
student *m;
gs->print();
m = gs;
m->print();
cin.get();
return 0;
}
Результат выполнения
Указатель на порожденный класс может быть неявно передан в указатель на базовый класс. При этом переменная-указатель m на базовый класс может указывать на объекты как базового, так и порожденного класса.
Указатель на порожденный класс может указывать только на объекты порожденного класса.
Неявные преобразования между порожденным и базовым классами называются предопределенными стандартными преобразованиями:
· объект порожденного класса неявно преобразуется к объекту базового класса.
· ссылка на порожденный класс неявно преобразуется к ссылке на базовый класс.
· указатель на порожденный класс неявно преобразуется к указателю на базовый класс.
Частное наследование
Порожденный класс может быть базовым для следующего порождения. При порождении privateнаследуемые члены базового класса, объявленные как protected и public, становятся членами порожденного класса с видимостью private. При этом члены базового класса с видимостью public и protected становятся недоступными для дальнейших порождений. Цель такого порождения — скрыть классы или элементы классов от использования в дальнейших порождениях. При порождении privateне выполняются предопределенные стандартные преобразования:
class grad_student : private student
{...};
int main() {...
grad_student *gs = &stud;
student *m;
gs->print();
m = gs; // ошибка
m->print();
cin.get();
return 0;
}
Однако порождение private позволяет отдельным элементам базового класса с видимостью public и protected сохранить свою видимость в порожденном классе. Для этого необходимо
· в части protected порожденного класса указать те наследуемые члены базового класса с видимостью protected, уточненные именем базового класса, для которых необходимо оставить видимость protected и в порожденном классе;
· в части public порожденного класса указать те наследуемые члены базового класса с видимостью public, уточненные именем базового класса, для которых необходимо оставить видимость public и в порожденном классе.
class X {
private:
int n;
protected:
int m;
char s;
public:
void func(int);
};
class Y : private X {
private:
...
protected:
...
X :: s;
public:
...
X :: func();
};
Возможен и третий вариант наследования – с использованием модификатора доступа protected.
Доступ к элементам базового класса из производного класса, в зависимости от модификатора наследования: