русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Деструктор


Дата добавления: 2015-07-09; просмотров: 894; Нарушение авторских прав


Деструктор является дополнением конструктора. Он имеет то же имя, что и класс, но с префексом-тильдой (~). Он вызывается всякий раз, когда уничтожается представитель класса. Для деструктора существуют следующие правила:

1. деструктор не может иметь аргументов;

2. деструктор не может возвращать значения;

3. деструктор не наследуется.

17. Параметризированные конструкторы

Конструкторам можно передавать аргументы. Для того, чтобы создать параметризированный конструктор, достаточно добавить параметры, как это делается для любой другой функции.

Общая форма передачи аргументов конструктору:

ярлык_класса объект(список_аргументов);

Пример

 

#include <iostream>

using namespace std;

 

class widget {

int i;

int j;

public:

widget(int a, int b);

void put_widget( );

};

 

widget::widget(int a, int b)

{

i = a;

j = b;

}

 

void widget::put_widget( )

{

cout << i << “ “ << j << “\n”;

}

 

int main( )

{

widget x(10, 20), y(0, 0);

 

x.put_widget( );

y.put_widget( );

 

return 0;

}

18. Дружественные функции

Разрешить обычной функции или функции-элементу другого класса полный доступ к элементам класса, объявленным private или protected, можно с помощью описания friend в определении данного класса.

Пример.

class myclass

{

friend void another_class::member(int);

friend void func_name(float);

};

Для друзей существуют следующие правила:

1. на описания friend не влияют спецификаторы public, protected или private;

2. описания friend не взаимны: если А объявляет В другом, то это не означает, что A является другом для B;

3. дружественность не наследуется: если А объявляет В другом, классы, производные от В, не будут автоматически получать доступ к элементам А;



4. дружественность не является переходным свойством: если А объявляет В другом, классы, производные от А, не будут автоматически признавать дружественность В.

 

19. Inline-функции

inline-функции – это такая функция, чьё тело подставляется в каждую точку вызова, вместо того, чтобы генерировать код вызова.

Общая форма объявления inline-функции следующая:

inline объявление_функции

Причина использования inline-функций заключается в их эффективности. Скорость выполнения программы возрастает. При этом может возрасти размер исполняемого кода.

Создание inline-функций внутри класса

Всякая функция, определенная внутри объявления класса, является автоматически inline-функцией, если только это допустимо.

20. Передача объектов в функции

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

Пример

 

#include <iostream>

using namespace std;

 

class myclass {

int i;

public:

myclass(int n);

~myclass( );

void set_i(int n) { i = n; }

int get_i( ) {return i; }

};

 

myclass:: myclass(int n)

{

i = n;

cout << "Constructing " << i << "\n";

}

myclass::~myclass( )

{

cout << "Destroying " << i << "\n";

}

void f(myclass ob);

 

int main()

{

myclass o(1);

 

f(o);

cout << "This is i in main: ";

cout << o.get_i( ) << "\n";

 

system("PAUSE");

return 0;

}

void f(myclass ob)

{

ob.set_i(2);

 

 

cout << "This is local i: " << ob.get_i( );

cout << "\n";

}

 

Эта программа выведет на экран следующие сообщения:

 

 

Имели место два вызова деструктора, в то время как конструктор вызывался только один раз. Хотя функция-конструктор не вызывалась при передаче объекта в функцию, необходимо вызывать деструктор при уничтожении копии. (Копия объекта уничтожается, как и любая локальная переменная, после окончания выполнения функции.)

Чтобы не возникало проблем необходимо определить оператор копирования для класса, который называется конструктором копирования.

21. Возвращение объектов функциями

Функция может возвращать объект в точку вызова.

Пример

 

#include <iostream.h>

using namespace std;

 

class myclass {

int i;

public:

void set_i(int n) { i = n; }

int get_i( ) {return i; }

};

 

myclass f( ); // возвращение объекта типа myclass

 

int main( )

{

myclass o;

 

o = f( );

cout << o.get_i( ) << “\n”;

return 0;

}

myclass f( );

{

myclass x;

x.set_i(1);

return x;

}

 

Когда функция возвращает объект, автоматически создается временный объект, содержащий возвращаемое значение. После того, как значение возвращено, этот объект уничтожается. Уничтожение временного объекта может вызвать неожиданные побочные эффекты. Для того чтобы преодолеть эту проблему используется перегрузка оператора присваивания и определение конструктора копирования.

 

22. Массивы объектов

Можно создавать массивы объектов точно так же, как создаются массивы данных других типов.

Инициализация массивов объектов

Если класс определяет конструктор с параметрами, то можно инициализировать каждый объект массива путем указания списка инициализации в точности так же, как это делается для массивов других типов. Однако точная форма списка инициализации будет определяться числом параметров конструктора.

Пример

#include <iostream>

using namespace std;

class cl{

int h;

int i;

public:

cl(int j, int k) {h=j; i=k;}

int get_i() {return i; }

int get_h() {return h;}

};

int main()

{

cl ob[3] = {

cl(1, 2),

cl(3, 4),

cl(5, 6)

};

int i;

for (i=0; i<3; i++) {

cout << ob[i].get_h();

cout << “, “;

cout << ob[i].get_i() << “\n”;

}

return 0;

}

Для создания неициализированных массивов необходимо иметь конструктор без параметров.

23. Указатели на объекты

 

В С++ можно получить доступ к объекту как непосредственно, так и используя указатель на объект.

Пример

#include <iostream>

using namespace std;

class P_example {

int num;

public:

void set_num(int val){num=val;}

void show_num();

};

void P_example::show_num()

{

cout << num << “\n”;

}

int main()

{

P_example ob, *p;

ob.set_num(1);

ob.show_num();

p=&ob;

p->show_num();

return 0;

}

24. Указатель this

Каждая нестатическая функция-элемент имеет доступ к объекту, для которого вызвана, через ключевое слово this. Типом this является:

тип_класса *.

Пример.

class simple

{

public:

simple();

void greet() { cout<<“ Hello!”;};

};

simple::simple()

{

greet(); // вызов

this->greet(); // функции

(*this).greet(); // greet()

}

Т.к. функции-элементы могут обращаться ко всем элементам класса просто по имени, в основном указатель this используется для возврата указателя (return this) или ссылки (return *this) на подразумеваемый объект.

25. Перегрузка операторов

 

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

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

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

 

тип имя_класса::operator#(список аргументов)

{

// действия, определённые применительно к классу

}

 

Здесь перегруженный оператор подставляется вместо символа #, а тип задает тип значений, возвращаемых оператором. Для того, чтобы упростить использование перегруженного оператора в сложных выражениях, в качестве возвращаемого значения часто выбирают тот же самый тип, что и класс, для которого перегружается оператор.

Пример

Листинг 1

Создаётся класс three_d, содержащий координаты объекта в трёхмерном пространстве. Следующая программа перегружает операторы + и = для класса three_d.

#include <iostream>

using namespace std;

 

class three_d {

int x,y,z;

public:

three_d operator+(three_d t);

three_d operator=(three_d t);

 

void show();

void assign(int mx, int my, int mz);

};

//

three_d three_d::operator+(three_d t)

{

three_d temp;

 

temp.x=x+t.x;

temp.y=y+t.y;

temp.z=z+t.z;

return temp;

}

//

three_d three_d::operator=(three_d t)

{

x=t.x;

y=t.y;

z=t.z;

return *this;

}

//

void three_d::show()

{

cout << x <<",";

cout << y <<",";

cout << z <<"\n";

}

//

void three_d::assign(int mx, int my, int mz)

{

x=mx;

y=my;

z=mz;

}

 

int main()

{

three_d a,b,c;

 

a.assign(1,2,3);

b.assign(10,10,10);

 

a.show();

b.show();

 

c=a+b;

c.show();

 

c=a+b+c;

c.show();

 

c=b=a;

c.show();

b.show();

 

return 0;

}

 

Если рассмотреть эту программу внимательно, может вызвать удивление, что обе функции-оператора имеют только по одному параметру, несмотря на то, что они перегружают бинарный оператор. Это связано с тем, что при перегрузке бинарного оператора с использованием функции-члена ей передаётся явным образом только один аргумент. Вторым аргументом служит указатель this, который передаётся ей неявно. Так, в строке

 

temp.x = x+t.x;

 

x соответствует this->x, где x ассоциировано с объектом, который вызывает функцию-оператор. Объект, стоящий справа от знака операции, передаётся функции.

При перегрузке унарной операции функция-оператор не имеет параметров, а при перегрузке бинарной операции функция-оператор имеет один параметр. (Нельзя перегрузить триадный оператор.) Во всех случаях объект, активизирующий функцию-оператор, передаётся неявным образом с помощью указателя this.

Тщательно проанализируем, как работает программа из листинга 1, начиная с перегруженного оператора +. Когда два объекта типа three_d подвергаются воздействию оператора +, значения их соответствующих координат складываются, как показано в функции operator+(), ассоциированной с данным классом. Обратим внимание на то, что функция не модифицирует значений операндов. Вместо этого она возвращает объект типа three_d, содержащий результат выполнения операции.

Другим ключевым моментом перегрузки оператора сложения является то, что он возвращает объект типа three_d. Хотя функция может иметь в качестве значения любой допустимый тип языка С++, то, что она возвращает объект типа three_d, позволяет использовать оператор + в более сложных выражениях, таких как a+b+c. Здесь a+b создаёт результат типа three_d. Это значение затем прибавляется к c.

В противоположность оператору +, оператор присваивания модифицирует свои аргументы. Поскольку функция operator=() вызывается объектом, стоящим слева от знака равенства, то именно этот объект модифицируется. Однако даже оператор присваивания обязан возвращать значение, поскольку оператор присваивания порождает величину, стоящую с правой стороны равенства. Так, для того чтобы выражение следующего вида

 

a = b = c = d;

 

было допустимым, необходимо, чтобы оператор operator=() возвращал объект, на который указывает this и который будет объектом, стоящим с левой стороны. Если сделать таким образом, то можно выполнить множественное присваивание.

Следующие операторы не могут быть перегружены:

 

. :: .* ?

26. Ссылки

Ссылка по существу является неявным указателем. Она используется как другое имя объекта.

Параметры-ссылки

По умолчанию С++ передаёт аргументы в функцию по значению.

В С++ можно создавать передаваемые по ссылке параметры. Для этого при объявлении функции перед параметром ставится знак амперсанта &.

Пример

void f(int &f)

{ f = rand( ); }

Инструкция

f = rand( );

не использует оператор *. При объявлении параметра-ссылки компилятор С++ знает, что это неявный указатель, и обрабатывает его соответствующим образом. Во фрагменте кода

int val;

f(val);

printf(“%d”, val);

адрес переменной val, а не значение этой переменной, передаётся функции f(). Благодаря этому функция f() может модифицировать значение переменной val. При вызове функции f() нет необходимости ставить оператор взятия адреса & перед переменной val.

 

На применение переменных ссылочного типа имеется ряд ограничений:

  1. Нельзя взять ссылку от переменной ссылочного типа, иными словами, нельзя взять её адрес.
  2. Нельзя создать массив ссылок.
  3. Нельзя создать указатель на ссылку.
  4. Ссылки на битовые поля не допускаются.

27. Наследование и спецификаторы доступа



<== предыдущая лекция | следующая лекция ==>
Доступ к элементам-данным | Наследование


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.016 сек.