2. Обекти, параметри
на фукции, динамична памет
Име | Действие |
Time() | Конструира обект, показващ текущото време |
Time(h,m,s) | Конструира обект, показващ h часа, m минути и s секунди |
t.get_seconds() | Връща броя на секундите в t. |
t.get_minutes() | Връща броя на минутите в t. |
t.get_hours() | Връща броя на часовете в t. |
t.add_seconds(n) | Премества t с n секунди напред. |
t.seconds_from(t2) | Пресмята броя на секундите между t и t2. |
Колко секунди остават до края на деня?
// time2.cpp
#include <iostream>
#include "ccc_time.h"
using namespace std;
int main()
{ Time now;
Time day_end(23, 59, 59);
long seconds_left =
day_end.seconds_from(now);
cout << "There are "
<< seconds_left
<< " seconds left in this day.\n";
return 0;
}
There are 44219 seconds left in this day. |
Тъй като денонощието съдържа 24x3600
=
86400 секунди, член-функцията seconds_from
връща стойност от тип long.
int main()
{ Employee harry("Hacker,
Harry", 45000.00);
double new_salary =
harry.get_salary() + 3000;
harry.set_salary(new_salary);
cout << "Name: "
<< harry.get_name() << endl;
cout << "Salary: "
<< harry.get_salary() << endl;
return 0;
}
Name: Hacker, Harry
Salary: 48000 |
В таблицата са дадени всички член-функции, дефинирани в класа Employee:
Име | Действие |
Employee(n,s) | Конструира обект, представящ служител с име n и заплата s. |
e.get_name() | Връща името на e. |
e.get_salary() | Връща заплатата на e. |
e.set_salary(s) | Дава нова стойност s на заплатата на e. |
Параметри на функции.
** Формални параметри -
параметри-променливи, задават се при дефиниране на функцията.
double future_value(double initial_balance,
double p, int nyear)
** Фактически параметри - представляват изрази за
инициализация на параметрите-променливи, указват се при
извикване на функцията.
b = future_value(total/2, rate,
year1-year2);
Фактическите параметри съответстват по тип и брой на формалните
параметри. В този пример променливите total и rate са от тип double, а year1 и year2 са от тип int .
/* декларация на функцията future_value */
double future_value(double
initial_balance, double p, int nyear);
int main()
{ ...
/* използване на функцията
future_value */
double bal =
future_value(10000, rate, 10);
...
}
/* дефиниция на функцията
future_value */
double future_value(double
initial_balance, double p, int nyear)
{
...
}
void print_time(Time t)
/* ЦЕЛ: отпечатва времето във формат
hh:mm:ss
ПОЛУЧАВА: t - времето,
което ще се отпечати
*/
{ cout << t.get_hours()
<< ":";
if (t.get_minutes() <
10) cout << "0";
cout <<
t.get_minutes() << ":";
if (t.get_seconds() <
10) cout << "0";
cout <<
t.get_seconds();
}
int main()
{ Time liftoff(7, 0, 15);
cout << "Liftoff:
"; print_time(liftoff); cout << "\n";
Time now;
cout << "Now: ";
print_time(now); cout << "\n";
return 0;
}
* Параметър-псевдоним не представлява нова
променлива, а друго име (псевдоним) на съществуваща променлива в
извикващата функция.
* Процедура raise_salary, която увеличава заплатата на служител с by процента.
//reisesal.cpp
#include <iostream>
#include "ccc_empl.h"
using namespace std;
void raise_salary(Employee& e, double
by)
/* ЦЕЛ: увеличава заплатата на даден
служител
RECEIVES: e - служител,
получаващ увеличение
by - процент на увеличението
*/
{ double new_salary =
e.get_salary() * (1 + by / 100);
e.set_salary(new_salary);
}
int main()
{ Employee harry("Hacker,
Harry", 45000.00);
raise_salary(harry, 5);
cout << "New
salary: " << harry.get_salary() << "\n";
return 0;
}
New salary: 47250 |
Формалният параметър Employee& e на функцията raise_salary е параметър-псевдоним на променливата harry от главната функция main.Промяната на стойността на параметъра-псевдоним e във функцията raise_salary води до промяна и на стойността на фактическия параметър (променливата) harry от функция main. Затова параметрите-псевдоними се наричат още входно-изходни параметри - те "пренасят" информация от извикващата функция към извиканата функция и обратно.
Константни псевдоними.
Използват се за да се избегне копирането -
особено нежелателно, ако параметърът е обект, съдържащ много
данни. Тъй като стойността на константния псевдоним не може да се
променя, той не "пренася" информация от извиканата функция в
извикващата функция.
void print_employee(Employee const
& e)
{
cout <<
"Name: " << e.get_name()
<< "Salary: " << e.get_salary();
}
параметри-променливи | параметри-псевдоними | константни псевдоними |
входни параметри за функцията | входно-изходни параметри за функцията | - |
предаване на параметри чрез копиране | предаване на параметри по адрес | предаване на параметри по адрес |
стойността на параметъра може да се променя | стойността на параметъра може да се променя | стойността на параметъра не може да се променя |
фактически параметър може да бъде константа, променлива или израз | фактически параметър може да бъде само променлива | фактически параметър може да бъде константа, променлива или израз |
** Дялове в оперативната памет при изпълнение на програма на С++.
CODE транслираната програма (изпълним файл) |
DATA глобални данни |
STACK локални променливи и константи имена на извикани функции |
Динамична памет (heap) |
**
Тип указател - съхранява адрес от оперативната памет на компютъра.
- дефиниране на променлива тип указател:
синтаксис: име
на тип * име
на променлива
Employee *boss;
int *pn;
-
запазване на място в динамичната памет - унарна операция new:
синтаксис:
new име на тип -
запазва място за една променлива от зададения тип
new име на тип(стойност)-
запазва място за една променлива от зададения тип и я инициалира
със зададената стойност
new име на
тип[число]-
запазва място за няколко променливи (колкото е числото) от
зададения тип.
-
дефиниране на променлива тип указател и задаване на начална
стойност на указателя:
int *pn = new int;
int *arr = new int[100];
-
дефиниране на променлива тип указател (boss), задаване на начална
стойност на указателя (операция new) и задаване на начална
стойност на сочения от него обект:
Employee *boss = new Employ("John",
3200);
int *pn = new int(10);
STACK
|
Динамична памет
адрес XXX
адрес YYY
|
-
стойност на указател - унарна операция *:
синтаксис: *указател
Employee harry("Harry", 1500);
*boss = harry;
*pn = 12;
cout << *pn;
-
операция стрелка ->:
синтаксис: указател
към клас -> член на класа
cout << (*boss).get_salary();
cout << boss->get_salary();
-
освобождаване на памет (унищожаване на обекта) - операция delete.
синтаксис: delete указател
delete boss;
delete pn;
- невалидни указатели.
int *pk = new int(10);
cout << *pk;
delete pk;
*pk = 100; /* невалиден указател */
Опасна грешка! Опит за работа със стойност
на указател след освобождаване на заетата памет.
-
операция адрес на променлива &.
синтаксис: & име на променлива
int k = 10; int *pk = &k; cout << k; cout << (*pk); |
STACK Адрес XXX
|
STACK
|
-
променливи-псевдоними.
int k = 10;
int &ak = k; /* дефиниране на
променлива-псевдоним */
if ( ak == k ) cout << "YES, of
course";
**
Указатели и масиви, адресна аритметика.
Името на масив е константен указател.
int a[3] = {10, 20, 30};
int *pa = a;
/* отпечатва 3 пъти стойността на
a[0] */
cout << a[0] <<"
"<< pa[0] <<" "<< *pa;
/* отпечатва 4 пъти стойността на
a[1] */
cout << a[1] <<"
"<< pa[1] <<" "<< *(pa+1) <<"
"<<(pa+1)[0];
Предефиниране на бинарна операция + за първи аргумент адрес и
втори аргумент цяло число.
Адрес | pa или a | pa+1 или a+1 | pa+2 или a+2 |
Стойност | 10 | 20 | 30 |
Индекс | 0 | 1 | 2 |
Достъп 1 | a[0] | a[1] | a[2] |
Достъп 2 | *pa | *(pa+1) | *(pa+2) |
Достъп 3 | pa[0] | (pa+1)[0] | (pa+1)[1] |
Достъп 4 | *a | *(a+1) | *(a+2) |