return ret;          // возвратить сохраненное состояние

}

Поскольку тип возвращаемого значения присутствует вне области видимости класса, следует указать, что он возвращает экземпляр BlobPtr, созданный с тем же типом, что и класс. В теле функции код находится в пределах класса, поэтому не нужно повторять аргумент шаблона при определении ret. Когда аргументы шаблона не предоставлены, компилятор подразумевает, что используется тот же тип, что и при создании экземпляра функции-члена. Следовательно, определение ret будет эквивалентно следующему:

BlobPtr ret = *this;

В области видимости шаблона класса можно обращаться к шаблону, не определяя его аргументы.

Шаблоны классов и дружественные отношения

Когда класс объявляет дружественные отношения (см. раздел 7.2.1), класс и его друг могут быть или не быть шаблонами. Шаблон класса, у которого есть друг, не являющийся шаблоном, предоставляет дружественный доступ ко всем экземплярам шаблона. Когда друг сам является шаблоном, предоставляющий дружественные отношения класс контролирует, распространяются ли они на все экземпляры шаблона или только на некий специфический экземпляр.

Дружественные отношения "один к одному"

Наиболее распространенная форма дружественных отношений между шаблоном класса и другим шаблоном (класса или функции) подразумевает дружбу между соответствующими экземплярами класса и его друга. Например, класс Blob должен объявить дружественным класс BlobPtr и шаблонную версию оператора равенства класса Blob (первоначально определенную для класса StrBlob в упражнении раздела 14.3.1).

Чтобы обратиться к определенному экземпляру шаблона (класса или функции), следует сначала объявить сам шаблон. Объявление шаблона включает список параметров шаблона:

// для объявления дружественных отношений в шаблоне Blob нужны

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

template class BlobPtr;

template class Blob; // необходимо для параметров operator==

template

 bool operator==(const Blob&, const Blob&);

template class Blob {

 // каждый экземпляр Blob предоставляет доступ к версии BlobPtr и

 // оператору равенства экземпляра, созданного с тем же типом

 friend class BlobPtr;

 friend bool operator==

  (const Blob&, const Blob&);

 // другие члены, как в разделе 12.1.1

};

Начнем с объявления Blob, BlobPtr и operator== шаблонами. Эти объявления необходимы для объявления параметра в функции operator== и дружественных объявлений в шаблоне Blob.

Объявления дружественными используют параметр шаблона Blob как собственный аргумент шаблона. Таким образом, дружба ограничивается этими экземплярами шаблона BlobPtr и оператора равенства, которые создаются с тем же типом:

Blob ca; // BlobPtr и operator== друзья

Blob ia;  // BlobPtr и operator== друзья

Члены класса BlobPtr могут обращаться к не открытым членам объекта ca (или любого другого объекта класса Blob), но объект ca не имеет никаких специальных прав доступа к объекту ia (или любому другому объекту класса Blob) или любому другому экземпляру класса Blob.

Общие и специфические дружественные отношения шаблонов

Класс может также сделать дружественным каждый экземпляр шаблона или ограничить дружбу специфическим экземпляром:

// предварительное объявление необходимо для объявления дружественных

// отношений со специфическим экземпляром шаблона

template class Pal;

class С { // С - обычный, не шаблонный класс

 friend class Pal; // экземпляр Pal создается с классом С как

                      // дружественным

 // все экземпляры Раl2 дружественны С;

 // при предоставлении дружественных отношений всем экземплярам

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

 template friend class Раl2;

};

template class C2 { // C2 - сам шаблон класса

 // у каждого экземпляра C2 есть тот же экземпляр Pal, что и у друга

 friend class Pal; // объявление шаблона для Pal должно быть в

                      // области видимости

Перейти на страницу:

Похожие книги