07 Localisation

454 views

Published on

Published in: Education, Sports
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
454
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
5
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

07 Localisation

  1. 1. Бублик Володимир Васильович Програмування - 2 Лекція 7. Процедурне програмування. Області видимості в програмі Лекції для студентів 2 курсу
  2. 2. Види імен <ul><li>Імена об'єктів </li></ul><ul><li>Імена типів (структур, класів ) </li></ul><ul><li>Імена функцій </li></ul><ul><li>Кожне ім'я має унікальну інтерпретацію в межах своєї області видимості, яка може складатися з кількох файлів, кожен з яких може компілюватися окремо </li></ul><ul><li>Для забезпечення можливості осібної компіляції до файлу з текстом програми (.cpp) додаються заголовні файли (.h) , в яких пояснюються (оголошуються) імена, необхідні для компіляції цього файлу </li></ul>
  3. 3. Визначення і оголошення <ul><li>Визначення приводить до створення об'єкту Визначення розміщують в .cpp файлах На підставі визначення будується об'єктний код побудови об'єкту </li></ul><ul><li>Оголошення пояснює існуючий об'єкт Оголошення розміщують в .h файлах Оголошення служать для побудови об'єктного коду, що використовує об'єкт </li></ul>
  4. 4. Визначення функції root.cpp <ul><li>double root ( double x, double eps) </li></ul><ul><li>{ </li></ul><ul><li>double s=0.5*x; </li></ul><ul><li>double t; </li></ul><ul><li>do </li></ul><ul><li>{ </li></ul><ul><li>t=s; </li></ul><ul><li>s=(s+x/s)*0.5; </li></ul><ul><li>} </li></ul><ul><li>while ((fabs(s-t)/s)>eps); </li></ul><ul><li>return s; </li></ul><ul><li>}; </li></ul>
  5. 5. Оголошення функції root <ul><li>// root .h </li></ul><ul><li>double root ( double x, double eps); </li></ul>
  6. 6. Використання функції root <ul><li>int main ( int argc, char * argv[]) </li></ul><ul><li>{ </li></ul><ul><li>const double two=2.0; </li></ul><ul><li>const double prec = 0.000001; </li></ul><ul><li>cout.precision(17); </li></ul><ul><li>// Де взяти інформацію про типи параметрів і результату? </li></ul><ul><li>cout << root (two, prec)<<endl; </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>
  7. 7. Використання функції root <ul><li># include &quot;root.h“ </li></ul><ul><li>int main ( int argc, char * argv[]) </li></ul><ul><li>{ </li></ul><ul><li>const double two=2.0; </li></ul><ul><li>const double prec = 0.000001; </li></ul><ul><li>cout.precision(17); </li></ul><ul><li>// З файлу root.h </li></ul><ul><li>cout << root (two, prec)<<endl; </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>
  8. 8. Омоніми <ul><li>Чи може ім'я root використовуватися в програмі за іншим призначенням? </li></ul><ul><li>Так, в іншій області видимості </li></ul>
  9. 9. Видимість <ul><li>Глобальна область видимості (вся програма) </li></ul><ul><li>Простори імен </li></ul><ul><li>Локальна область видимості </li></ul><ul><ul><li>блок, </li></ul></ul><ul><ul><li>функція, </li></ul></ul><ul><ul><li>файл, </li></ul></ul><ul><ul><li>клас ( з'явиться пізніше) </li></ul></ul>
  10. 10. Глобальна область видимості <ul><li>Глобальна область видимості об'єкти, функції і типи, визначені за межами блоків будь-якого типу </li></ul>
  11. 11. Глобальні визначення <ul><li>//unit1.cpp </li></ul><ul><li>int g_Var = 20; // Визначення глобальної змінної </li></ul><ul><li>void f( void ) //Визначення функції </li></ul><ul><li>{ </li></ul><ul><li>cout<<&quot;I am f () from unit1 and I see g_Var=&quot;; </li></ul><ul><li>cout<<g_Var<<endl; </li></ul><ul><li>return ; </li></ul><ul><li>} </li></ul><ul><li>Функція void f( void ) бачить змінну g_Var , оскільки вони визначені в одному файлі </li></ul>
  12. 12. Доступ до глобальних імен і функцій <ul><li>Як відкомпілювати програму, що використовує глобальні об'єкти з іншого файлу? Як дати функції int main() можливість побачити змінну g_Var ? </li></ul><ul><li>//unit2.cpp </li></ul><ul><li>int main () </li></ul><ul><li>{ </li></ul><ul><li>cout<<g_Var<<endl; //Як використати змінну </li></ul><ul><li>f(); // g_Var з unit1.cpp? </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>
  13. 13. Заголовний файл <ul><li>Для розповсюдження інформації про об'єкти, визначені у файлі unit1.cpp , створюємо заголовний файл </li></ul><ul><li>//unit1.h </li></ul><ul><li>// Оголошення глобальних об'єктів </li></ul><ul><li>void f( void ); </li></ul><ul><li>extern int g_ Var ; </li></ul><ul><li>Оголошення функції відрізняється від визначення відсутністю її тіла. </li></ul><ul><li>Щоб відрізнити оголошення змінної від її визначення додають ключове слово extern </li></ul>
  14. 14. Використання оголошень <ul><li>//unit2.cpp </li></ul><ul><li># include “unit1.h&quot; </li></ul><ul><li>// #include “unit1.cpp“ </li></ul><ul><li>// чому не коректно приєднувати текст .cpp файлу? </li></ul><ul><li>int main () </li></ul><ul><li>{ </li></ul><ul><li>cout<<g_Var<<endl; //Використано оголошення </li></ul><ul><li>f(); //з unit1.h </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>extern int g_ Var ; void f(void);
  15. 15. Глобальні типи <ul><li>Де розміщувати визначення структур? </li></ul><ul><li>struct Point </li></ul><ul><li>{ </li></ul><ul><li>double _x, _y; </li></ul><ul><li>}; </li></ul><ul><li>Якщо безпосередньо в .cpp файлі, то як дати доступ до цього визначення з різних файлів? </li></ul><ul><li>Якщо в заголовному файлі .h , то як усунути повторні визначення при приєднанні одного заголовного файлу до різних .cpp файлів? </li></ul>
  16. 16. Захист заголовного файлу <ul><li>Заголовні файли захищають від повторного включення в текст програми при одночасній компіляції багатьох файлів </li></ul><ul><li>//File Point.h </li></ul><ul><li>#ifndef _POINT_H_ </li></ul><ul><li>#define _POINT_H_ </li></ul><ul><li>struct Point </li></ul><ul><li>{ </li></ul><ul><li>double _x, _y; </li></ul><ul><li>}; </li></ul><ul><li>#endif </li></ul>
  17. 17. Оголошення типів <ul><li>Чи всі програмні файли потребують визначення структури і відповідного #include ? ― Ні, часом досить лише оголошення структури </li></ul><ul><li>Часто #include в іншому заголовному файлі недоречний ( доробка на майбутнє ) </li></ul><ul><li>//Some.h </li></ul><ul><li>struct Point; // оголошення структури </li></ul><ul><li>// досить для указника без ініціалізації </li></ul><ul><li>Point * p; </li></ul><ul><li>//досить для оголошення функції без виклику </li></ul><ul><li>Point sum (Point a, Point b); </li></ul>
  18. 18. Простір імен. Оголошення <ul><li>Простір імен дає можливість зібрати пов'язані між собою позначення в одному місці та відрізняти їх від інших імен з глобального контексту </li></ul><ul><li>//File.h </li></ul><ul><li>void f( void ); </li></ul><ul><li>namespace myNames </li></ul><ul><li>{ </li></ul><ul><li>void f( void ); </li></ul><ul><li>void g ( void ); </li></ul><ul><li>} </li></ul><ul><li>Тут присутні дві різні функції void f( void ) </li></ul>
  19. 19. Визначення елементів простору імен <ul><li>//File.cpp </li></ul><ul><li>void f( void ) </li></ul><ul><li>{ </li></ul><ul><li>cout<<&quot;I am global&quot;; </li></ul><ul><li>return ; </li></ul><ul><li>} </li></ul><ul><li>void myNames:: f(void) </li></ul><ul><li>{ </li></ul><ul><li>cout<<&quot;I am f from myNames&quot;; </li></ul><ul><li>return ; </li></ul><ul><li>} </li></ul>
  20. 20. Операція розв'язання області видимості <ul><li>//Source.cpp </li></ul><ul><li># include &quot;File.h &quot; </li></ul><ul><li>int main () </li></ul><ul><li>{ </li></ul><ul><li>f(); //взяти f з глобального контексту </li></ul><ul><li>myNames :: f(); //взяти f з простору myNames </li></ul><ul><li>myNames :: g(); //взяти g з простору myNames </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>
  21. 21. Приєднати простір імен <ul><li>//Source.cpp </li></ul><ul><li># include &quot;File.h &quot; </li></ul><ul><li>using namespace myNames; </li></ul><ul><li>int main () </li></ul><ul><li>{ </li></ul><ul><li>:: f(); //взяти f з глобального контексту </li></ul><ul><li>myNames :: f(); //взяти f з простору myNames </li></ul><ul><li>g(); //взяти g з простору myNames </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul>
  22. 22. Стандартний простір імен std <ul><li>Стандартний простір імен містить визначення імен і типів </li></ul><ul><li>Наприклад, </li></ul><ul><li>cin, с out , endl </li></ul><ul><li>istream , ostream </li></ul><ul><li>Їх можна вживати через операцію розв'язання області дії </li></ul><ul><li>std:: с out , std:: endl </li></ul><ul><li>std:: ostream , std:: istream </li></ul><ul><li>Наприклад, </li></ul><ul><li>std::cout<<&quot;x=&quot;<<x<<std::endl; </li></ul><ul><li>Можна приєднати простір імен </li></ul><ul><li>using namespace std; </li></ul>
  23. 23. Локальна область видимості <ul><li>Кожна функція і блок визначають свою власну локальну область видимості. Вона складається з області видимості, в якій знаходиться блок чи визначення функції, доповненої власним простором імен. </li></ul><ul><li>Деякі імена з ширшого контексту при цьому можуть затінятися локальними іменами. </li></ul><ul><li>Погодження. Локальні області видимості не можуть містити визначень функцій , але можуть містити визначення типів даних </li></ul>
  24. 24. Розв'язання глобальної області видимості <ul><li>i nt x = 1; </li></ul><ul><li>int main () </li></ul><ul><li>{ </li></ul><ul><li>int x = 2; </li></ul><ul><li>cout<<&quot;x=&quot;<<x<<endl; //локальна х </li></ul><ul><li>cout<<&quot;::x=&quot;<< ::x <<endl; //глобальна х </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul><ul><li>Локальна змінна затіняє однойменну змінну з ширшого контексту. Розв'язання (доступ до глобальної) можливе </li></ul>
  25. 25. Глобальні об'єкти <ul><li>Рекомендується уникати глобальних об'єктів (чому?), але глобальні сталі абсолютно правомірні </li></ul><ul><li>Визначення </li></ul><ul><li>//some.cpp </li></ul><ul><li>const float pi = 3.14159; </li></ul><ul><li>Оголошення </li></ul><ul><li>//some.h </li></ul><ul><li>extern const float pi; </li></ul>
  26. 26. Вкладені блоки <ul><li>Область видимості блоку включає глобальний контекст, в якому цей блок знаходиться, доповнений локальними об'єктами з блоку </li></ul><ul><li>Чим вужча область видимості кожного об'єкту, тим краще </li></ul><ul><li>double x, y;…………………… </li></ul><ul><li>if (x>y) </li></ul><ul><li>{ </li></ul><ul><li>double z = x; x=y; e=z; </li></ul><ul><li>} </li></ul><ul><li>cout<< z ; //ERROR: undeclared identifier </li></ul>
  27. 27. Вкладені блоки <ul><li>int main () </li></ul><ul><li>{ </li></ul><ul><li>int x = 1 ; </li></ul><ul><li>{ </li></ul><ul><li>int x = 2; </li></ul><ul><li>cout<<&quot;x=&quot;<<x<<endl; //синя х </li></ul><ul><li>} </li></ul><ul><li>cout<<&quot;x=&quot;<<x<<endl; //зелена х </li></ul><ul><li>return 0; </li></ul><ul><li>} </li></ul><ul><li>Внуьтрішня змінна затіняє однойменну локальну змінну з ширшого контексту. Розв'язання неможливе </li></ul>
  28. 28. Область видимості функції <ul><li>Область видимості функції включає глобальний контекст ( краще, щоб його не було), в якому це визначення знаходиться, доповнений параметрами та локальними об'єктами з тіла функції </li></ul><ul><li>const int n=10 ; </li></ul><ul><li>double prod( double x[], double y[] ) </li></ul><ul><li>{ //{ n } + { x, y, sum} + {i} </li></ul><ul><li>double sum = 0; </li></ul><ul><li>for ( int i=0; i<n; i++) </li></ul><ul><li>sum += x[i]*y[i]; </li></ul><ul><li>return sum; </li></ul><ul><li>} </li></ul>
  29. 29. Файл як область видимості <ul><li>Можна обмежити видимість об'єктів .cpp файлом, у якому вони визначені. Такі об'єкти називають статичними </li></ul><ul><li>//some.cpp </li></ul><ul><li>static unsigned currentID = 0; </li></ul><ul><li>void increaseID() </li></ul><ul><li>{ ++currentID; return ;} </li></ul><ul><li>int getFreeID() </li></ul><ul><li>{ increaseID(); return currentID; } </li></ul>
  30. 30. Персистентність <ul><li>Персистентність визначає тривалість життя об'єктів від моменту зв'язування до моменту видалення </li></ul><ul><li>Зв'язування об'єкту з його значенням </li></ul><ul><li>раннє (статичне) </li></ul><ul><li>пізнє (динамічне) </li></ul>
  31. 31. Статичне зв'язування <ul><li>При складанні програми </li></ul><ul><li>константи препроцесора (уникаємо їх – чому?) # define PI 3.14159 </li></ul><ul><li>ім'я функції з її тілом void f() { cout <<« I am f()&quot;<<endl; return; } </li></ul><ul><li>При компіляції </li></ul><ul><li>іменовані константи const float pi = 3.14159; </li></ul><ul><li>глобальні і статичні змінні static unsigned int currentID = 0; </li></ul>
  32. 32. Динамічне зв'язування <ul><li>Після входу в блок { double z=x; x=y; y=z;} </li></ul><ul><li>При виклику функції u = root (v, e); // double x = v , double eps = e </li></ul><ul><li>При виділенні пам'яті int * p = new int (1); </li></ul>
  33. 33. Тривалість життя <ul><li>Локальні об'єкти живуть до кінця виконання блоку чи функції (в стеку) </li></ul><ul><li>Створені програмою (за допомогою new ) об'єкти живуть, доки їм дозволяє програма ( видалення за допомогою delete) (в купі , in heap) </li></ul><ul><li>Глобальні і статичні об'єкти живуть до кінця виконання програми </li></ul><ul><li>Постійні об'єкти можуть зберігатися у файлах (базах даних) і жити вічно </li></ul>
  34. 34. Призначення об'єктів <ul><li>Кожній змінній ― одне призначення </li></ul><ul><li>// Багатоцільові змінні ознака кепського тону! </li></ul><ul><li>temp = sqrt(b*b – 4*a*c) </li></ul><ul><li>root[0] = (-b -temp)/(2*a); </li></ul><ul><li>root[1] = (-b+temp)/(2*a); </li></ul><ul><li>…………………… . </li></ul><ul><li>temp = root[0]; </li></ul><ul><li>root[0] = root[1]; </li></ul><ul><li>rout[1] = temp; </li></ul>
  35. 35. Призначення об'єктів <ul><li>Кожній змінній ― одне призначення </li></ul><ul><li>// Добре </li></ul><ul><li>double discriminant = sqrt(b*b – 4*a*c) </li></ul><ul><li>root[0] = (-b - discriminant )/(2*a); </li></ul><ul><li>root[1] = (-b+ discriminant )/(2*a); </li></ul><ul><li>…………………… . </li></ul><ul><li>double replacer = root[0]; </li></ul><ul><li>root[0] = root[1]; </li></ul><ul><li>rout[1] = replacer ; </li></ul>
  36. 36. Вибір імен <ul><li>Ім'я повинно виражати суть об'єкту </li></ul><ul><li>Чим ширша область видимості об'єкту, тим важливіша виразність його імені. Імена виду x, i, k, тощо, якщо вживаються, то вказують на те, що їх область видимості кілька рядків </li></ul><ul><li>Приклади </li></ul><ul><li>currentDate, linesPerPage </li></ul><ul><li>done, found </li></ul>
  37. 37. Дисципліна іменування <ul><li>Корисно називати об'єкти так, щоб ім'я виражало його роль. Корисно розрізняти </li></ul><ul><li>імена типів, наприклад, size_t </li></ul><ul><li>імена структур і класів ― зазвичай з великої літери, наприклад, Point, Collection </li></ul><ul><li>імена членів структур, наприклад, _x </li></ul><ul><li>імена констант, наприклад, LOCAL_CONSTANT, kConst </li></ul><ul><li>глобальні імена, наприклад, gThisGlobal </li></ul><ul><li>Особливо важлива дисципліна іменування у великих проектах </li></ul>

×