Šablona přátel
Třída šablony mohou mít Přátelé.Třída nebo šablonu třídy, funkce nebo funkce šablony lze přítele šablonu třídy.Přátelé lze také specializace šablonu třídy nebo funkce šablony, ale není dílčí specializace.
Příklad
V následujícím příkladu je funkce přítele definována jako funkce šablony do šablony třídy.Tento kód vytvoří verzi funkce přítele pro každý vytváření instance šablony.Tato konstrukce je užitečné, pokud váš přítel funkce závisí na stejné parametry šablony jako třída.
// template_friend1.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
template <class T> class Array {
T* array;
int size;
public:
Array(int sz): size(sz) {
array = new T[size];
memset(array, 0, size * sizeof(T));
}
Array(const Array& a) {
size = a.size;
array = new T[size];
memcpy_s(array, a.array, sizeof(T));
}
T& operator[](int i) {
return *(array + i);
}
int Length() { return size; }
void print() {
for (int i = 0; i < size; i++)
cout << *(array + i) << " ";
cout << endl;
}
template<class T>
friend Array<T>* combine(Array<T>& a1, Array<T>& a2);
};
template<class T>
Array<T>* combine(Array<T>& a1, Array<T>& a2) {
Array<T>* a = new Array<T>(a1.size + a2.size);
for (int i = 0; i < a1.size; i++)
(*a)[i] = *(a1.array + i);
for (int i = 0; i < a2.size; i++)
(*a)[i + a1.size] = *(a2.array + i);
return a;
}
int main() {
Array<char> alpha1(26);
for (int i = 0 ; i < alpha1.Length() ; i++)
alpha1[i] = 'A' + i;
alpha1.print();
Array<char> alpha2(26);
for (int i = 0 ; i < alpha2.Length() ; i++)
alpha2[i] = 'a' + i;
alpha2.print();
Array<char>*alpha3 = combine(alpha1, alpha2);
alpha3->print();
delete alpha3;
}
Další příklad zahrnuje přítele, který má šablona specializace.Šablona specializace funkce se automaticky přítele, pokud je původní funkce šablony přítele.
Je také možné deklarovat jako přítele jako komentář před prohlášení přítele následující kód označuje speciální verze šablony.Je-li to provést, je třeba vložit definici šablony specializace přítele mimo šablonu třídy.
// template_friend2.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
template <class T>
class Array;
template <class T>
void f(Array<T>& a);
template <class T> class Array
{
T* array;
int size;
public:
Array(int sz): size(sz)
{
array = new T[size];
memset(array, 0, size * sizeof(T));
}
Array(const Array& a)
{
size = a.size;
array = new T[size];
memcpy_s(array, a.array, sizeof(T));
}
T& operator[](int i)
{
return *(array + i);
}
int Length()
{
return size;
}
void print()
{
for (int i = 0; i < size; i++)
{
cout << *(array + i) << " ";
}
cout << endl;
}
// If you replace the friend declaration with the int-specific
// version, only the int specialization will be a friend.
// The code in the generic f will fail
// with C2248: 'Array<T>::size' :
// cannot access private member declared in class 'Array<T>'.
//friend void f<int>(Array<int>& a);
friend void f<>(Array<T>& a);
};
// f function template, friend of Array<T>
template <class T>
void f(Array<T>& a)
{
cout << a.size << " generic" << endl;
}
// Specialization of f for int arrays
// will be a friend because the template f is a friend.
template<> void f(Array<int>& a)
{
cout << a.size << " int" << endl;
}
int main()
{
Array<char> ac(10);
f(ac);
Array<int> a(10);
f(a);
}
V dalším příkladu šablony třídy přítele deklarována v rámci šablony třídy.Šablona třídy potom slouží jako argument šablona třídy přítele.Šablony třídy přítel musí definovaná mimo šablonu třídy, které jsou deklarovány.Všechny specializace nebo částečné specializace přítele šablony jsou také přátelé původní šablonu třídy.
// template_friend3.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
template <class T>
class X
{
private:
T* data;
void InitData(int seed) { data = new T(seed); }
public:
void print() { cout << *data << endl; }
template <class U> friend class Factory;
};
template <class U>
class Factory
{
public:
U* GetNewObject(int seed)
{
U* pu = new U;
pu->InitData(seed);
return pu;
}
};
int main()
{
Factory< X<int> > XintFactory;
X<int>* x1 = XintFactory.GetNewObject(65);
X<int>* x2 = XintFactory.GetNewObject(97);
Factory< X<char> > XcharFactory;
X<char>* x3 = XcharFactory.GetNewObject(65);
X<char>* x4 = XcharFactory.GetNewObject(97);
x1->print();
x2->print();
x3->print();
x4->print();
}