Връщане на стойност по връзка
(Returning by Reference)
В предишната лекция разгледахме предаването на аргументи по връзка (отпратка) - call-by-reference. В настоящата ще разгледаме връщането на стойност по връзка. Една от причините за този начин на рефериране на променливи е, че функцията може да се използва в лявата страна на оператора за присвояване (знака равно), все едно че е променлива. Това изглежда странно на пръв поглед, защото компилатора не третира извикването на функция като променлива, а го разглежда като константа. Т.е. израз от рода на
somefunc() = intvar; // doesn't mean anything
не би имал смисъл с типа функциии, които разгледахме досега и би приличало на присвояването по-долу, което няма няма смисъл.
7 = intvar; // doesn't mean anything
защото 7 е константа, а не променлива. Константата определено не е lvalue! Последният термин означава, че това е израз (в частен случай - променлива), на която може да се присвоява стойност. Обикновено константите и литералите (7 е константа-литерал) са rvalue, което означава, че могат да се появяват само от дясната страна на оператора за присвояване (знака равно).
1. Връщане по връзка (Returning by Reference). Ето една примерна програма от превъзходния курс на Лафоор [1], в която функцията връща стойност по връзка.
//
retref.cpp
//
demonstrates returning by reference
#include
<iostream.h>
class
omega
{
private:
int data;
public:
int & getnset()
// returns OR SETS data
{
// (note ampersand)
return data;
}
};
void
main()
{
omega om1;
// make an object
om1.getnset() = 92;
// give it a value (!) CALLING BY REFERENCE!!!
cout << "om1 = "
<< om1.getnset(); // get the
value and display it
}
В главната функция, main(), функцията getnset() се извиква два пъти. Второто извикване е обичайното, с което сме свикнали - то връща стойността на променливата data на класа omega. При първото извикване на функцията getnset() тя е разположена отляво на оператора за присвояване - om1.getnset() = 92;. Това на практика води до присвояване на стойността 92 на променливата data на класа omega.
2. Деклариране на функция, която връща по връзка. Както се вижда от горната програма, за да може една функция да връща стойност по връзка са необходими две неща. Първо, в декларацията (и/или дефиницията, както е по-горе) да се постави амперсанд, &, след типа на променливата, която се връща от функцията:
int & getnset()
Второ, функцията трябва да връща променливата, която искаме да връщаме по връзка или искаме на нея да присвояваме стойности. Това е направено с реда
return data;
в тялото на функцията getnset().
Разбира се, за да присвоим стойност на променливата data на класа omega трябва да извикаме функцията отляво на оператора за присвояване! Както това е направено в главната функция на горната програма:
om1.getnset() = 92; // CALLING BY REFERENCE!!!
! Ограничения: Не се опитвайте да връщате по стойност автоматични променливи (за тези променливи вижте лекция 27), т.е. променливи, които са дефинирани в тялото на функцията. Както бе написано в тази предишна лекция, тези променливи изчезват след извикването на функцията и затова вие просто ще присвоявате някъде в паметта стойности и това може да наруши работата на софтуера на Вашия компютър. Т.е. не се опитвайте да пишете код от рода на следния:
//
THIS IS A BAD CODE!!!
int
& badret() //
returns by reference
{
int somevar; // local
variable
. . .
return somevar; // don't do this
}
Разбира се, компилаторът не ще Ви позволи да пишете такъв код - например компилаторът на Борланд Билдер 5.0 (Borland C++ Builder) издава следното съобщение още за тялото на функцията:
Attempting to return a reference to local variable 'somevar'.
Връщането по връзка се използва най-вече при презаредените оператори (overloaded operators) - с тази концепция ще се запознаем в следващите лекции.
Keywords: С++,
OOP programming , C++ , Classes , Inheritance , Reusability , Creating
New Data Types , Polymorphism and Overloading
Ключови думи: клас
, обект, обектно ориентирано програмиране , полиморфизъм switch if else
?