План:
Функциите като черни кутии
Писане на функции
Коментари и документиране
Връщане на стойност и оператор return
Параметри на функции
Деклариране на функции
Странични ефекти и процедури
Параметри-псевдоними
** Функциите като черни кутии
Функция е част от код, определена с име.
До сега сме използвали редица функции, които са предоставени:
-- от системните библиотеки на С++
sqrt(x) - пресмята корен квадратен на числото с
плаваща точка x
getline(cin, s) - чете
един ред от потока cin
-- като член-функции от класа string на Стандартната библиотека
с шаблони на С++
s.length() - връща дължината на низа s
-- от потребителските класове Time и Employee,
дефинирани в учебника
t.get_second() - връща секундите от обекта t на класа Time
Функциите могат да се разглеждат като черни кутии, като знаем
само вход и изход, без да се интересуваме как работи функцията.
- Изпълнението на main() временно се прекратява докато се изпълнява функцията sqrt.int main()
{ cout << "Enter a positive number: ";
double x;
cin >> x;
x = sqrt(x); // sqrt is running
cout << "The result is " << x << "\n";
return 0;
}
|
|
член-функция | неявен параметър | тип
на неявен параметър |
явен параметър |
тип на явен параметър |
harry.get_salary() | harry | Employee | няма |
- |
t.add_seconds(10) | t | Time | 10 |
int |
s.substr(0,num) | s | string | 0, num |
int, string |
функция | върната стойност |
sqrt(x) | double type |
c.substr(0, num) | string type |
t.get_seconds() | int type |
getline(cin,s) | no return value |
функция | изисквания за
параметрите - тип и lvalue/rvalue |
fabs(w) | параметърът w трябва да е от тип double
- константа, променлива, израз (rvalue) |
t.second_from(t1) | параметърът t1 трябва да е обект от класа Time - константа, променлива |
getline(cin,s) | първият параметър трябва да бъде cin,
вторият параметър трябва да е променлива (lvalue) от тип
string |
double future_value(double p)Функцията се дефинира като се укаже:
{ double b = 1000 * pow(1 + p / 100, 10);
return b;
}
// futval1.cppТвърдо свързани стойности - да се избягват!
#include <iostream>
#include <cmath>
using namespace std;
// дефиниция на функция
double future_value(double p)
{ double b = 1000 * pow(1 + p / 100, 10);
return b;
}
int main()
{ cout << "Please enter the interest rate in percent: ";
double rate;
cin >> rate;
// извикване на функция
double balance = future_value(rate);
cout << "After 10 years, the balance is "
<< balance << "\n";
return 0;
}
double future_value(double initial_balance, double p, int n)
{ double b = initial_balance * pow(1 + p / 100, n);
return b;
}
futval.cppdouble balance = future_value(1000, rate, 10);
/**Може да се използва и показания формат за български език.
Computes the value of an investment with compound interest.
@param initial_balance - the initial value of the investment
@param p the interest rate per period in percent
@param n the number of periods the investment is held
@return the balance after n periods
*/
double future_value(double initial_balance, double p, int n)
{ double b = initial_balance * pow(1 + p / 100, n);
return b;
}
Всеки клон на функцията (вследствие на оператор if) трябва да връща някаква стойност.double future_value(double initial_balance, double p, int n)
{ if (n < 0) return 0;
if (p < 0) return 0;
double b = initial_balance * pow(1 + p / 100, n);
return b;
}
Последният оператор на всяка функция би трябвало да бъде оператор return.double future_value(double initial_balance, double p, int n)
{ if (p >= 0)
return initial_balance * pow(1 + p / 100, n);
/* Error */
}
Функция, която връща булева стойност се нарича предикат.bool approx_equal(double x, double y)
{ const double EPSILON = 1E-14;
if (x == 0) return fabs(y) <= EPSILON;
if (y == 0) return fabs(x) <= EPSILON;
return fabs(x - y) / max(fabs(x), fabs(y)) <= EPSILON;
}
// approx.cpp
#include <iostream>
#include <algorithm>
using namespace std;
/**
Tests whether two floating-point numbers are
approximately equal.
@param x a floating-point number
@param y another floating-point number
@return true if x and y are approximately equal
*/
bool approx_equal(double x, double y)
{ const double EPSILON = 1E-14;
if (x == 0) return fabs(y) <= EPSILON;
if (y == 0) return fabs(x) <= EPSILON;
return fabs(x - y) / max(fabs(x), fabs(y)) <= EPSILON;
}
int main()
{ double x;
cout << "Enter a number: ";
cin >> x;
double y;
cout << "Enter another number: ";
cin >> y;
if (approx_equal(x, y))
cout << "The numbers are approximately equal.\n";
else
cout << "The numbers are different.\n";
return 0;
}
** Параметри на функции.
* Формални параметри -
параметри-променливи, които се задават при дефиниране на
функцията.
double future_value(double initial_balance, double p, int n)
* Фактически параметри (аргументи) -
представляват изрази за инициализация на
параметрите-променливи и се задават при извикване на
функцията.
b = future_value(total/2, rate, year2-year1);
Фактическите параметри съответстват по тип и брой на формалните параметри: променливите total и rate са от тип double, а year1 и year2 са от тип int .
Формалните параметри са променливи, които може да се променят
в тялото на функцията.
double future_value(double initial_balance, double p, int n)
{ p = 1 + p / 100;
double b = initial_balance * pow(p, n);
return b;
}
Често това се счита за лош стил на програмиране (bad
programming style).
// printime.cpp
#include <iostream>
#include <iomanip>
using namespace std;
#include "ccc_time.h"
/**
Print a time in the format h:mm:ss
@param t the time to print
*/
void print_time(Time t)
{ cout << t.get_hours() << ":" << setw(2) << setfill('0')
<< t.get_minutes() << ":" << setw(2)
<< t.get_seconds() << setfill(' ');
}
int main()
{ Time liftoff(7, 0, 15);
Time now;
cout << "Liftoff: ";
print_time(liftoff);
cout << "\n";
cout << "Now: ";
print_time(now);
cout << "\n";
return 0;
}
** Параметри-псевдоними.
Досега използваните параметри на функции сe наричат параметри-променливи.
Параметрите-променливи са променливи, които се дефинират при извикване на функцията и са различни от променливите в извикващата функция.
Параметър-псевдоним (reference parameter) не създава нова променлива, а е друго име (псевдоним) на съществуваща променлива в извикващата функция.
Всяка промяна на стойността на параметъра-псевдоним е промяна и на съответната променлива в извикващата функция.
Пример: Функция за увеличаване на заплата.
Процедурата raise_salary увеличава заплатата на служител e с by процента.
raise_salary(harry, 5);
void raise_salary(Employee& e, double by)
{ double new_salary = e.get_salary() * ( 1 + by / 100);
e.set_salary(new_salary);
}
// raisesal.cpp
#include <iostream>
using namespace std;
#include "ccc_empl.h"
/**
Raise an employee salary
@param e employee receiving raise
@param by the percentage of the raise
*/
void raise_salary(Employee& e, double 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;
}
Формалният параметър Employee&
e на
функцията raise_salary е параметър-псевдоним
на променливата harry от главната функция main.
Промяната на стойността на параметъра-псевдоним e във функцията raise_salary води до промяна и
на стойността на фактическия параметър (променливата) harry от функция main.
Параметрите-псевдоними се наричат още входно-изходни параметри -
те пренасят информация от извикващата функция към извиканата
функция и обратно.