Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ответы на вопросы Осадчий А.В. гр.010902.docx
Скачиваний:
9
Добавлен:
24.04.2019
Размер:
143.34 Кб
Скачать

21. Статические члены класса.

Класс - это тип, а не некоторое данное, и для каждого объекта класса создается своя копия членов, представляющих данные. Однако, наиболее удачная реализация некоторых типов требует, чтобы все объекты этого типа имели некоторые общие данные. Лучше, если эти данные можно описать как часть класса. Например, в операционных системах или при моделировании управления задачами часто нужен список задач:

class task {

// ...

static task* chain;

// ...

};

Описав член chain как статический, мы получаем гарантию, что он будет создан в единственном числе, т.е. не будет создаваться для каждого объекта task. Но он находится в области видимости класса task, и может быть доступен вне этой области, если только описан в общей части. В этом случае имя члена должно уточняться именем класса:

if (task::chain == 0) // какие-то операторы

В функции-члене его можно обозначать просто chain. Использование статических членов класса может заметно сократить потребность в глобальных переменных.

Описывая член как статический, мы ограничиваем его область видимости и делаем его независимым от отдельных объектов его класса. Это свойство полезно как для функций-членов, так и для членов, представляющих данные:

class task {

// ...

static task* task_chain;

static void shedule(int);

// ...

};

Но описание статического члена - это только описание, и где-то в программе должно быть единственное определение для описываемого объекта или функции, например, такое:

task* task::task_chain = 0;

void task::shedule(int p) { /* ... */ }

Естественно, что и частные члены могут определяться подобным образом.

Отметим, что служебное слово static не нужно и даже нельзя использовать в определении статического члена класса. Если бы оно присутствовало, возникла бы неоднозначность: указывает ли оно на то, что член класса является статическим, или используется для описания глобального объекта или функции? Слово static одно из самых перегруженных служебных слов в С и С++. К статическому члену, представляющему данные, относятся оба основных его значения: "статически размещаемый" , т.е. противоположный объектам, размещаемым в стеке или свободной памяти, и "статический" в смысле с ограниченной областью видимости, т.е. противоположный объектам, подлежащим внешнему связыванию. К функциям-членам относится только второе значение static.

22.Перегрузка операций. Перегрузка операций "+", "+=" и операции [].

Как вы уже знаете, тип переменной определяет набор значений, которые она может хранить, а также набор операций, которые можно выполнять над этой переменной. Например, над значением переменной типа int ваша программа может выполнять сложение, вычитание, умножение и деление. С другой стороны, использование оператора плюс для сложения двух строк лишено всякого смысла. Когда вы определяете в своей программе класс, то по существу вы определяете новый тип. А если так, C++ позволяет вам определить операции, соответствующие этому новому типу.

Суть перегрузки состоит в изменении смысла оператора (например, оператора плюс (+), который обычно в C++ используется для сложения) при использовании его с определенным классом.

Перегрузка операций "+"

Когда вы перегружаете оператор для какого-либо класса, то смысл данного оператора не изменяется для переменных других типов. Например, если вы перегружаете оператор плюс для класса string, то смысл этого оператора не изменяется, если необходимо сложить два числа. Когда компилятор С++ встречает в программе оператор, то на основании типа переменной он определяет ту операцию, которая должна быть выполнена.

Ниже приведено определение класса, создающее класс string. Этот класс содержит один элемент данных, который представляет собой собственно символьную строку. Кроме того, этот класс содержит несколько различных методов и пока не определяет каких-либо операторов:

class string

{

public:

string(char *); // Конструктор

void operator +(char *);

void show_string(void);

private:

char data[256] ;

};

void string::operator +(char *str)

{

strcat(data, str);

}

void main(void)

{

string title( "Учимся программировать на C++");

title.show_string();

title + " я учусь!";

title.show_string() ;

}

Перегрузка операции +=

class Counter

{

private:

counter;

int a=2;

public:

Counter() : counter(0) {}

void operator+= ()

{

counter ++ 1;

}

};

int main(){

Counter a;

+=a;

+=a;

+=a;

};

перегрузка операции индексации []

Чтобы задать смысл индексов для объектов класса используется

функция operator[]. Второй параметр (индекс) функции operator[]

может быть любого типа. Это позволяет определять ассоциативные

массивы и т.п.

Описываем:

class Person { ... };

class AdressBook

{

public:

Person &operator [](int);// доступ к i

protected:

// содержит в качестве компонентных данных множество объектов типа

// Person представляемых как динамический массив, список или дерево

...

};

Person &AdressBook::operator [](int i)

{ ... }

int main(void)

{

AdressBook persons;

Person record;

...

record = persons[3];

...

}

23.Перегрузка операций "*", "->" и операции ().

Некоторые операторы в C++ не перегружаются в принципе. По всей видимости, это сделано из соображений безопасности.

  • Оператор выбора члена класса ".".

  • Оператор разыменования указателя на член класса ".*"

  • В С++ отсутствует оператор возведения в степень (как в Fortran) "**".

  • Запрещено определять свои операторы (возможны проблемы с определением приоритетов).

  • Нельзя изменять приоритеты операторов

Перегрузка операции вызова функции

Это операция '()'. Она является бинарной операцией. Первым операндом обычно является объект класса, вторым – список параметров.

Пример.

class Matrix // двумерный массив вещественных чисел

{

public:

...

double operator ()(int, int); //доступ к элементам матрицы по индексам

};

double Matrix::operator() (int i, int j)

{ ... }

int main (void)

{

Matrix a;

double k;

...

k = a(5, 6);

...

}

Операция '–>' доступа к компоненту класса через указатель на объект этого класса рассматривается как унарная. Пусть a – объект класса A, в котором перегружена операция '–>'. Тогда выражение a–>m интерпретируется как (a.operator–>())–>m. Это означает, что функция operator –>() должна возвращать указатель на класс A, или объект класса A, или ссылку на класс A.

24.Перегрузка операций ++ и --.

Унарные операции инкремента ++ и декремента -- существуют в двух формах: префиксной и постфиксной. В современной спецификации С++ определен способ, по которому компилятор может различить эти две формы. В соответствии с этим способом задаются две версии функции operator ++() и operator --(). Они определены следующим образом:

Префиксная форма:

operator ++();

operator --();

Постфиксная форма:

operator ++(int);

operator --(int);

Указание параметра int для постфиксной формы не специфицирует второй операнд, а используется только для отличия от префиксной формы.

Пример.

class Person

{

public:

...

void operator ++()

{

++age;

}

void operator ++(int)

{

age++;

}

protected:

int age;

...

};

int main(void)

{

Person John;

John++;

++John;

}