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.

Доступ к элементам базового класса из производного класса, в зависимости от модификатора наследования: