首页 > 编程语言 >C++类模板与友元详解

C++类模板与友元详解

时间:2024-03-16 15:45:13浏览次数:26  
标签:友元 函数 C++ operator Pair class 模板

C++ 模板

下面分四种情况分别讨论。

1. 函数、类、类的成员函数作为类模板的友元

函数、类、类的成员函数都可以作为类模板的友元。程序示例如下:

void Func1() {  }
class A {  };
class B
{
public:
    void Func() { }
};
template <class T>
class Tmpl
{
    friend void Func1();
    friend class A;
    friend void B::Func();
};
int main()
{
    Tmpl<int> i;
    Tmpl<double> f;
    return 0;
}

类模板实例化时,除了类型参数被替换外,其他所有内容都原样保留,因此任何从 Tmp1 实例化得到的类都包含上面三条友元声明,因而也都会把 Func1、类 A 和 B::Func 当作友元。

2. 函数模板作为类模板的友元

例题:在《C++类模板(模板类)》一节中我们定义了 Pair 模板,将<<运算符重载为一个函数模板,并将该函数模板作为 Pair 模板的友元,这样,任何从 Pair 模板实例化得到的对象都能用<<运算符通过 cout 输出。

程序代码如下(函数模板作为类模板的友元):

#include <iostream>
#include <string>
using namespace std;
template <class T1, class T2>
class Pair
{
private:
    T1 key;  //关键字
    T2 value;  //值
public:
    Pair(T1 k, T2 v) : key(k), value(v) { };
    bool operator < (const Pair<T1, T2> & p) const;
    template <class T3, class T4>
    friend ostream & operator << (ostream & o, const Pair<T3, T4> & p);
};
template <class T1, class T2>
bool Pair <T1, T2>::operator< (const Pair<T1, T2> & p) const
{  //“小”的意思就是关键字小
    return key < p.key;
}
template <class Tl, class T2>
ostream & operator << (ostream & o, const Pair<T1, T2> & p)
{
    o << "(" << p.key << "," << p.value << ")";
    return o;
}
int main()
{
    Pair<string, int> student("Tom", 29);
    Pair<int, double> obj(12, 3.14);
    cout << student << " " << obj;
    return 0;
}

程序的输出结果是:

(Torn, 29) (12, 3.14)


第 13、14 行将函数模板 operator<< 声明为类模板 Pair 的友元。在 Visual Studio 中,这两行也可以用下面的写法替代:

friend ostream & operator<< <T1, T2>(ostream & o, const Pair<T1, T2> & p);

但在 Dev C ++ 中,替代后编译就无法通过了。

编译本程序时,编译器自动生成了两个 operator << 函数,它们的原型分别是:

ostream & operator << (ostream & o, const Pair<string, int> & p);
ostream & operator << (ostream & o, const Pair<int, double> & p);

前者是 Pair <string, int> 类的友元,但不是 Pair<int, double> 类的友元;后者是 Pair<int, double> 类的友元,但不是 Pair<string, int> 类的友元。

3. 函数模板作为类的友元

实际上,类也可以将函数模板声明为友元。程序示例如下:

#include <iostream>
using namespace std;
class A
{
    int v;
public:
    A(int n) :v(n) { }
    template <class T>
    friend void Print(const T & p);
};
template <class T>
void Print(const T & p)
{
    cout << p.v;
}
int main()
{
    A a(4);
    Print(a);
    return 0;
}

程序的输出结果是:

4


编译器编译到第 19 行Print(a);时,就从 Print 模板实例化出一个 Print 函数,原型如下:

void Print(const A & p);

这个函数本来不能访问 p 的私有成员。但是编译器发现,如果将类 A 的友元声明中的 T 换成 A,就能起到将该 Print 函数声明为友元的作用,因此编译器就认为该 Print 函数是类 A 的友元。

思考题:类还可以将类模板或类模板的成员函数声明为友元。自行研究这两种情况该怎么写。

4. 类模板作为类模板的友元

一个类模板还可以将另一个类模板声明为友元。程序示例如下:

#include <iostream>
using namespace std;
template<class T>
class A
{
public:
    void Func(const T & p)
    {
        cout << p.v;
    }
};
template <class T>
class B
{
private:
    T v;
public:
    B(T n) : v(n) { }
    template <class T2>
    friend class A;  //把类模板A声明为友元
};
int main()
{
    B<int> b(5);
    A< B<int> > a;  //用B<int>替换A模板中的 T
    a.Func(b);
    return 0;
}

程序的输出结果是:

5

在本程序中,A< B<int> > 类成为 B<int> 类的友元。

标签:友元,函数,C++,operator,Pair,class,模板
From: https://www.cnblogs.com/uacs2024/p/18077136

相关文章

  • 模板整理
    整理遇到的几个比较难记的算法的模板。KMP算法KMP算法是字符串匹配算法,通常是在长字符串中对短字符串(模式串)进行匹配。使用next数组对模式串的前缀表进行记录。前缀表:当匹配失败时,将根据这个前缀表决定指针的位置。前缀表的目的是找到模式串中相等的前缀和后缀。例如aabaaf,......
  • C++类模板中的静态成员
    C++模板类模板中可以定义静态成员,从该类模板实例化得到的所有类都包含同样的静态成员。程序示例如下:#include <iostream>using namespace std;template <class T>class A{private:    static int count;public:    A() { count ++; }    ~A()......
  • C++学习笔记——001
    C++是一种静态类型的、编译式的、通用的、大小写敏感的、不规则的编程语言,支持过程化编程、面向对象编程和泛型编程。C++是C的一个超集,事实上,任何合法的C程序都是合法的C++程序。注意:使用静态类型的编程语言是在编译时执行类型检查,而不是在运行时执行类型检查。 <>......
  • P3374 【模板】树状数组 动态求连续区间和 刷题笔记
    我们创建如下的树状数组来辅助操作该数组每个s[i]处于第几层取决于其二进制最后低位的1处于从右往左数第几列显然所有奇数的最右边一位都是1即其最低位的1处于右边第一列所以所有的奇数处于第一层而2,6,10,14的最低位1处于右边第二列 所以这些数处于第二层 8的最......
  • C++类模板与继承详解
    C++模板类模板和类模板之间、类模板和类之间可以互相继承。它们之间的派生关系有以下四种情况。1.类模板从类模板派生示例程序:template <class T1, class T2>class A{    Tl v1; T2 v2;};template <class T1, class T2>class B : public A <T2,......
  • C++算法学习心得八.动态规划算法(3)
    1.最后一块石头的重量II(1049题)题目描述:有一堆石头,每块石头的重量都是正整数。每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x和 y,且 x<=y。那么粉碎的可能结果如下:如果 x==y,那么两块石头都会被完全粉碎;如果 x!=y,那么重量为 x 的......
  • 南京邮电大学C++实验(一)类和对象的定义及使用(仅参考)
    实验名称:类和对象的定义及使用一、实验目的和要求(1)掌握类与对象的定义与使用方法,理解面向对象方法中通过对象间传递消息的工作机制。(2)正确掌握类的不同属性成员的使用方法。(3)掌握构造函数与析构函数的概念,理解构造函数与析构函数的执行过程。(4)掌握友元函数和友元类的定义......
  • C++模板的显式实例化
    C++模板前面讲到的模板的实例化是在调用函数或者创建对象时由编译器自动完成的,不需要程序员引导,因此称为隐式实例化。相对应的,我们也可以通过代码明确地告诉编译器需要针对哪个类型进行实例化,这称为显式实例化。编译器在实例化的过程中需要知道模板的所有细节:对于函数模板,也就是......
  • 将C++模板应用于多文件编程
    C++模板在将函数应用于多文件编程时,我们通常是将函数定义放在源文件(.cpp文件)中,将函数声明放在头文件(.h文件)中,使用函数时引入(#include命令)对应的头文件即可。编译是针对单个源文件的,只要有函数声明,编译器就能知道函数调用是否正确;而将函数调用和函数定义对应起来的过程,可以延迟到......
  • 邻接表存储带权的无向图(c++题解)
    题目描述给出一个无向带权图,顶点数为n,边数为m。输入格式第一行两个整数n,m,接下来有m行,每行3个整数u,v,w,表示点u到点v有一条边,边权为w。输出格式第i行输出第点i的所有邻接点,按照点i到该点的边权由小到大输出,如果边权相等,则按照点的编号有小到大输出。样例样例输入复......