Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Передача параметрів

4.3. Передача параметрів значенням, особливості передачі параметрів у випадку указників, псевдонімів, псевдонімів сталих, псевдонімів указників, масивів, псевдонімів масивів; замовчувані значення параметрів; перетворення типів при передачі параметрів

 

Як ми побачили з попереднього розділу в С++ підтримується передача параметрів значенням. Власне це єдиний спосіб передачі параметрів, якщо не рахувати текстових підстановок в макровизначеннях. Передача параметрів значенням має багато переваг, головною з яких є її висока надійність. Підпрограма не має виходу за рамки відведеної їй пам’яті, а тому сфера її впливу добре локалізується. Разом з тим добре відомі проблеми, що виникають при передачі параметрів значенням, а саме проблеми зміни значень фактичних параметрів.

 

Ось приклад

void DoubleMyValue (short valueParam)

{

valueParam *= 2;

}

int main ()

{

short number = 10;

DoubleMyValue (number);

cout<<number<<’\n’;

}

 

В результаті виконання підпрограми значення формального параметру valueParam подвоїться, але це подвоєння не справить жодного впливу на фактичний параметр number. Складена в такий спосіб програма стає марною. Правда, в цьому конкретному випадку ситуацію легко поправити

 

 

p>Результат виконання програми:

 

Перед swap(): i: 10 j: 20

Після swap(): i: 10 j: 20

 

Перший вихід із проблемної ситуації пропонують указники.


Як і раніше параметри передаються значеннями, але значення ці тепер адреси.

 

Перед swap(): i: 10 j: 20

Після swap(): i: 20 j: 10

 

 

void rswap(int &x, int &y)

{

int z = x; x=y; y=z;

}

int main() {

int i = 10;

int j = 20;

cout<<"Перед swap():\ti: "<<i<<"\tj: "<<j<<endl;

rswap(i, j);

cout<<"Після swap():\ti: "<<i<<"\tj: "<<j<<endl;

return 0;

}

 

 

 

 

void pswap(int *x, int *y)

{

int z = *x; *x=*y; *y=z;

cout<<"pswap: "<<&x<<" z:"<<&z<<endl;

}

void rswap(int &x, int &y)

{

int z = x; x=y; y=z;

cout<<"rswap: "<<&x<<" z:"<<&z<<endl;

}

void swap(int x, int y)

{

int z = x; x=y; y=z;

cout<<"rswap: "<<&x<<" z:"<<&z<<endl;

}

int main() {

int i = 10, &ri = i;

int j = 20;

cout<<"main: "<<hex<<&i<<" ri: "<<&ri<<endl;

cout<<"Перед swap():\ti: "<<i<<"\tj: "<<j<<endl;

swap(i, j);

cout<<"Після swap():\ti: "<<i<<"\tj: "<<j<<endl;

pswap(&i, &j);

cout<<"Після pswap():\ti: "<<i<<"\tj: "<<j<<endl;

rswap(i, j);

cout<<"Після rswap():\ti: "<<i<<"\tj: "<<j<<endl;

return 0;

}

 

Оголошення int *&v;читається справа наліво: псевдонім указника

 

void ptrswap(int *&, int *&);

int main()

{

int i = 10;

int j = 20;

int *pi = &i;

int *pj = &j;

cout<<"Перед ptrswap():\tpi: "

<<*pi<<"\tpj: "<<*pj<<endl;

ptrswap(pi, pj);

cout<<"Після ptrswap():\tpi: "

<<*pi<<"\tpj: "<<*pj<<endl;

return 0;

}

 

 

Перед ptrswap: pi: 10 pj: 20

Після ptrswap: pi: 20 pj: 10

 

 

У цьому прикладі 1000 разів копіюватиметься масив з 1000 чисел незалежно від того, у чому полягатиме обчислення функції calc, наприклад це могла б бути сума або середнє арифметичне.

 

 

 

Якщо ми замінимо сигнатуру, задавши параметр псевдонімом, уникнемо копіювання, але не будемо гарантовані від зміни параметру всередині функції

 

int calc(Huge &par);

 

 

void getArray(int[ 10 ]);

і

void getPtr(int*);

 

Треба добре розуміти, що оскільки масив передається указником, він не копіюється. Порівняйте з попереднім прикладом, де передавався елемент масиву, що в свою чергу був визначений як структура.

 

 

void putValues(int[ ], int size);

int main()

{

int i, j[ 2];

putValues(&i, 1);

putValues(j, 2);

return 0;

}

 

void putValues(int (&arr)[10]);

int main()

{

int i, j [ 2 ];

putValues(i);

// помилкака: аргумент не є масивом

putValues(j);

// помилка:

// аргумент не є масивом з 10 елементів типу int

return 0;

}

 

 

p>Додатковий параметр sz відповідає за розмірність. Перша перевірка з’ясовує, чи були указники попередньо встановлені. Те ж саме копіювання символьних масивів додаткового параметру розмірності не потребує, оскільки вичерпання масиву перевіряється нульовим кодом

 

void сopyString (char *source, char *dest)

{

while (*source!= ‘\0’)

{

*dest = *source;

dest++;

source++;

}

*dest = ‘\0’;

}

 

або це ж саме компактним С-текстом

 

void CopyString (char *source, char *dest)

{

while (*dest++ = *source++);

}

 

Для функцій існує можливість визначати замовчувані значення аргументів. Замовчування визначаються або безпосередньо в реалізації функції, або при визначенні її прототипу. Останній спосіб видається більш доцільним.

 

void GenerateATone (short frequency = 440)

{

//Частота 440 відповідає ноті сі

};

 

Виклики можуть бути такими

 

GenerateATone (330);

GenerateATone ();

 

Для визначення замовчувань у багатомісних функціях існує одне обмеження: всі аргументи без початкових значень повинні передувати у списку аргументів усім аргументам з замовчуваними значеннями. Так прототип

 

void NormalDefaults (short x, short y=2, short z=3);

 

відповідає правилу, в той час як наступний — ні, оскільки перший аргумент має, а другий аргумент не має замовчування

 

void WillNotCompile (long time = 100L, short stack);

 

Використання замовчуваних значень аргументів при виклику функції ілюструється наступним прикладом.

 

#include <iostream.h>

void MyFunc(short param1,

short param2 = 0,

short param3 = 0);

int main()

{

MyFunc(1);

MyFunc(1, 2);

MyFunc(1, 2, 3);

return 0;

}

void MyFunc(short param1,

short param2,

short param3)

{

cout << "MyFunc(" << param1

<< ", " << param2

<< ", " << param3

<< ")\n";

}

MyFunc(1, 0, 0)

MyFunc(1, 2, 0)

MyFunc(1, 2, 3)

 

<== предыдущая лекция | следующая лекция ==>
Вбудовані (inline) функції, порівняння з макровизначеннями, закриті функції | Обчислення значення функцій
Поделиться с друзьями:


Дата добавления: 2014-01-04; Просмотров: 401; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




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