C++ Template 基础篇(四):模板与友元

Template 基础篇-模板与友元

Template所代表的泛型编程是C++语言中的重要的组成部分,我将通过几篇blog对这半年以来的学习做一个系统的总结,本文是基础篇的第四部分。

类友元

类模板之间、类模板与普通类之间共有三种友元的形式:

友元普通类类模板
普通类不在讨论范围内类模板友元
类模板类友元类模板的类模板友元

普通类的类模板友元

一对一关系

可以将类模板的一个实例声明为普通类的友元。

template <typename T>
class Pal {
public:
    static void Call(T& t) {
        t.show();
    }
};

class HasFriend {
//只有Pal<HasFriend>才是友元,其他实例不行。
//注意这里将未完整定义的class放入了模板。
friend class Pal<HasFriend>; 
private:
    void show() {
        cout << "Calling private method" << endl;
    }
};

HasFriend hf;
Pal<HasFriend>::Call(hf); //Pal<HasFriend>是HasFriend的友元
一对多关系

也可以把类模板声明为类的友元模板,这意味着这个类模板的所有实例都是类的友元。声明时要使用template和class关键字(这一点和模板的模板参数很像)。

template <typename T> class Pal;

class HasFriend {
template <typename T> friend class Pal; //注意这里的template、class关键字与friend的前后关系
private:
    void show() {
        cout << "Calling private method" << endl;
    }
};

template <typename T>
class Pal {
public:
    static void Call(HasFriend& hf) {
        hf.show();
    }
};

HasFriend hf;
Pal<void>::Call(hf); //Pal<void>是HasFriend的友元
Pal<int>::Call(hf); //Pal<int>是HasFriend的友元

类模板的普通类友元

可以将一个普通类声明为类模板的友元。

class Pal;

template <typename T>
class HasFriend {
friend class Pal;
private:
    void show() {
        cout << "Calling private method" << endl;
    }
};

class Pal {
public:
    static void Call() {
        HasFriend<int> hf;
        hf.show();
    }
};

Pal::Call(); //Pal是HasFriend<int>的友元

类模板的类模板友元

一对一关系

可以通过共享类型参数T,在类模板与类模板友元之间达成一对一的关系。

template <typename T>
class Pal;

template <typename T>
class HasFriend {
friend class Pal<T>;
private:
    void show() {
        cout << "Calling private method" << endl;
    }
};

template <typename T>
class Pal {
public:
    static void Call() {
        HasFriend<T> hf;
        hf.show();
    }
};

Pal<int>::Call(); //Pal<int>是HasFriend<int>的友元
多对多关系

为类模板友元声明一个不同的类型参数,可以达到多对多关系,也就是说template B的所有实例都是template A的所有实例的友元。

template <typename T>
class Pal;

template <typename T>
class HasFriend {
template <typename U> friend class Pal;
private:
    void show() {
        cout << "Calling private method" << endl;
    }
};

template <typename T>
class Pal {
public:
    static void Call() {
        HasFriend<int> hf;
        hf.show();
    }
};

Pal<double>::Call(); //Pal<double>是HasFriend<int>的友元
Pal<void>::Call(); //Pal<void>是HasFriend<int>的友元

函数友元

类(类模板)与函数(函数模板)之间共有三种友元的形式:

友元普通函数函数模板
普通类不在讨论范围内函数模板友元
类模板函数友元类模板的函数模板友元

普通类的函数模板友元

一对一关系

可以将函数模板的一个实例声明为普通类的友元。

template <typename T>
void call(T& t) {
    t.show();
}

class HasFriend {
friend void call<HasFriend>(HasFriend&);
private:
    void show() {
        cout << "Calling private method" << endl;
    }
};

HasFriend hf;
call(hf); //ok, void call<HasFriend>(HasFriend&)是HasFriend的友元
一对多关系

也可以把函数模板声明为类的友元模板,这意味着这个函数模板的所有实例都是类的友元。声明时注意要使用template关键字。

template <typename T, typename U>
void call(T& t, U& u) {
    cout << t << endl;
    u.show();
}

class HasFriend {
template <typename T, typename U> friend void call(T&, U&);
private:
    void show() {
        cout << "Calling private method" << endl;
    }
};

HasFriend hf;
int i = 1;
call(i, hf); //void call(int&, HasFriend&)是HasFriend的友元,注意这里的类型自动推导
double d = 2.0;
call(d, hf); //void call(double&, HasFriend&)是HasFriend的友元,注意这里的类型自动推导

类模板的函数友元

可以将一个普通函数声明为类模板的友元,这样,这个普通函数就是这个类模板的所有实例的友元。

void call();

template <typename T>
class HasFriend {
friend void call();
private:
    void show() {
        cout << "Calling private method" << endl;
    }
};

void call() {
    HasFriend<int> hf1; 
    HasFriend<double> hf2;
    hf1.show(); //ok,友元
    hf2.show(); //ok,友元
}

call();

类模板的函数模板友元

一对一关系

可以通过共享类型参数T,在类模板与函数模板友元之间达成一对一的关系。

template <typename T>
void call(const T& t);

template <typename T>
class HasFriend {
friend void call<T>(const T& t);
private:
    void show() {
        cout << "Calling private method" << endl;
    }
};

template <typename T>
void call(const T& t) {
    HasFriend<T> hf;
    hf.show();
}

call(1); //ok,共享同一个类型实参int
多对多关系

为函数模板友元声明一个不同的类型参数,可以达到多对多关系。

template <typename T>
void call(const T& t);

template <typename T>
class HasFriend {
template <typename U> friend void call(const U& u);
private:
    void show() {
        cout << "Calling private method" << endl;
    }
};

template <typename T>
void call(const T& t) {
    HasFriend<int> hf;
    hf.show();
}

call(1.0f); //call<float>是HasFriend<int>的友元
call(2.0); //call<double>是HasFriend<int>的友元

模板参数友元

在C++11中,我们还可以将模板类型参数声明为友元。

template <typename T>
class HasFriend {
friend T; //T是HasFriend<T>的友元
private:
    void show() {
        cout << "Calling private method" << endl;
    }
};

class Pal {
public:
    static void call() {
        HasFriend<Pal> hf;
        hf.show();
    }
};

Pal::call();
  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值