Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lucik_op.doc
Скачиваний:
0
Добавлен:
23.12.2019
Размер:
2.88 Mб
Скачать

Параметры ссылки

Если требуется предоставить возможность функции изменять значения передаваемых в нее параметров, то в языке С они должны быть объявлены либо глобально, либо работа с ними в функции осуществляется через передаваемые в нее указатели на эти переменные. В С++ аргументы в функцию можно передавать также и через ссылку. Для этого при объявлении функции перед параметром ставится знак &.

#include <iostream.h>

void fun1(int,int);

void fun2(int &,int &);

void main()

{ int i=1,j=2; // i и j – локальные параметры

cout << "\n адрес переменных в main() i = "<<&i<<" j = "<<&j;

cout << "\n i = "<<i<<" j = "<<j;

fun1(i,j);

cout << "\n значение i = "<<i<<" j = "<<j;

fun2(i,j);

cout << "\n значение i = "<<i<<" j = "<<j;

}

void fun1(int i,int j)

{ cout << "\n адрес переменных в fun1() i = "<<&i<<" j = "<<&j;

int a; // при вызове fun1 i и j из main() копируются

a=i; i=j; j=a; // в стек в переменные i и j при возврате в main()

} // они просто теряются

void fun2(int &i,int &j)

{ cout << "\n адрес переменных в fun2() i = "<<&i<<" j = "<<&j;

int a; // здесь используются ссылки на переменные i и j

a=i; i=j; j=a; // из main() (вторые их имена) и т.о. действия в

// функции производятся с теми же переменными i и j

}

В функции fun2 в инструкции

a=i;

не используется операция *. При объявлении параметра-ссылки компилятор С++ определяет его как неявный указатель (ссылку) и обрабатывает соответствующим образом. При вызове функции fun2 ей автоматически передаются адреса переменных i и j. Таким образом, в функцию передаются не значения переменных, а их адреса, благодаря чему функция может модифицировать значения этих переменных. При вызове функции fun2 знак & перед переменными i и j ставить нельзя.

Независимые ссылки

В языке С++ ссылки могут быть использованы не только для реализации механизма передачи параметров в функцию. Они могут быть объявлены в программе наряду с обычными переменными, например:

#include <iostream.h>

void main()

{ int i=1;

int &j=i; // j – ссылка (второе имя) переменной i

cout << "\n  адрес переменных i = "<<&i<<" j = "<<&j;

cout << "\n значение i = "<<i<<" j = "<<j;

j=5; //

cout << "\n  адрес переменных i = "<<&i<<" j = "<<&j;

cout << "\n значение i = "<<i<<" j = "<<j;

}

В результате работы программы будет получено:

адрес переменных i = 0xадрес1 j = 0xадрес2

значение i = 1 j = 1

адрес переменных i = 0xадрес1 j = 0xадрес2

значение i =5 j = 5

В этом случае компилятор создает временный объект j, которому присваивается адрес ранее созданного объекта i. Далее j может быть использовано как второе имя i.

Практические приемы ограничения числа объектов класса

Иногда для эффективной работы желательно ограничивать число объектов. Пусть, например, разрабатывается класс для принтера. При этом в системе необходимо при множестве клиентов (заданий, объектов класса PrntJob) иметь только один объект (принтер, объект класса Printer). Это может быть достигнуто инкапсуляцией объекта принтер в одну из функций. Все конструкторы класса Printer должны быть закрытые и могут быть вызваны только из открытых методов класса Printer или методов дружественных этому классу. Кроме того, создаваемый объект является статическим, что исключает возможность его повторного создания.

#include <iostream>

using std::cout;

using std::endl;

#include <string>

using std::string;

class PrntJob; // предварительное объявление

class Printer // класс принтер

{ Printer(){}

Printer(const Printer& obj){};

public:

void Job(PrntJob&); // функция вывода задания

friend Printer& Print(); // функция возвращает ссылку

}; // на объект "принтер"

class PrntJob // класс задание

{ string str;

public:

void get(const string str) // инициализация задания

{this->str=str;}

string& put(){return str;} // возврат ссылки на текущее задание

};

void Printer::Job(PrntJob& obj)

{cout<<obj.put()<<endl;

}

Printer& Print()

{ static Printer pr; // статический объект "принтер"

return pr; // возврат ссылки на объект"принтер"

}

main()

{ PrntJob ob1,ob2;

ob1.get("задание 1");

ob2.get("задание 2");

// cout<<&Print()<<endl; // выодится адрес объекта принтер

Print().Job(ob1);

// cout<<&Print()<<endl;

Print().Job(ob2);

}

В результате работы программы получим:

задание 1

задание 2

Если при этом выводить адреса объекта принтер, создаваемого для вывода первого и второго задания, то получим одинаковые адреса. Следовательно, можно утверждать, что в функции Print создается единственный объект для вывода всех заданий.

Можно поступить иначе, сделав функцию Print статической членом-функцией класса Printer. Это также исключает необходимость использования friend-механизма для функции Print.

class Printer // класс принтер

{ Printer(){}

Printer(const Printer& obj){};

public:

static Printer& Print(); // создание статического объекта принтер

. . .

};

class PrntJob // класс задание

{ . . .

};

Printer& Printer::Print()

{ static Printer pr; // статический объект "принтер"

return pr; // возврат ссылки на объект"принтер"

}

main()

{ . . .

Printer::Print().Job(ob1); // вызов объекта принтера для объекта задания

Printer::Print().Job(ob2);

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]