首页 > 编程语言 >C++Primer Plus 第十四章代码重用:模板类和友元14.4.9 ----002

C++Primer Plus 第十四章代码重用:模板类和友元14.4.9 ----002

时间:2024-06-30 23:30:53浏览次数:21  
标签:友元 14.4 void HasFriendT C++ template 具体化 模板

C++Primer Plus 第十四章代码重用:模板类和友元14.4.9

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:模板类和友元14.4.9


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


2.模板类的约束模板友元函数

可以修改前一个示例,使友元函数本身成为模板。具体地说,为约束模板友元作准备,要使类的每个具体化都获得与友元匹配的具体化。这比非模板友元复杂些,包含以下3步。首先,在类定义的前面声明每个模板函数。

template <typename T> void counts();
template <typename T>void report(T &);

然后,在函数中再次将模板声明为友元。这些语句根据类模板参数的类型声明具体化:

template <typename TT>
class HasFriendT
friend void counts<TT>();
friend void report<>(HasFriendT<TT> &);

}:声明中的>指出这是模板具体化。对于 repon(),一可以为空,因为可以从函数参数推断出如下模板类型参数:HasFriendT
然而,也可以使用:

report<HasFriendT<TT>>(HasFriendT<TT>&)

但 counts()函数没有参数,因此必须使用模板参数语法()来指明其具体化。还需要注意的是,TT是HasFriendT类的参数类型。
同样,理解这些声明的最佳方式也是设想声明一个特定具体化的对象时,它们将变成什么样。例如,假设声明了这样一个对象:

HasFriendT<int>squack;

编译器将用int替换 TT,并生成下面的类定义:class HasFriendT

friend void counts<int>();
friend void report<>(HasFriendT<int> &);

基于 TT 的具体化将变为 int,基于 HasFriend的具体化将变为 HasFriend。因此,模板具体化counts( )和 report<HasFriendT>( )被声明为 HasFriendT类的友元。
程序必须满足的第三个要求是,为友元提供模板定义。程序清单14.23说明了这3个方面。请注意,程序清单 14.22包含1个 count()函数,它是所有 HasFriend 类的友元;而程序清单 14.23包含两个 count()函数,它们分别是某个被实例化的类类型的友元。因为count()函数调用没有可被编译器用来推断出所需具体化的函数参数,所以这些调用使用count和coount()指明具体化。但对于repor()调用,编译器可以从参数类型推断出要使用的具体化。使用>格式也能获得同样的效果:

report<HasFriendT<int>>(hfi2);/same as report(hfi2);

程序清单14.23 tmp2tmp.cpp

// tmp2tmp.cpp -- template friends to a template class
#include <iostream>
using std::cout;
using std::endl;

// template prototypes
template <typename T> void counts();
template <typename T> void report(T &);

// template class
template <typename TT>
class HasFriendT
{
private:
    TT item;
    static int ct;
public:
    HasFriendT(const TT & i) : item(i) {ct++;}
    ~HasFriendT() { ct--; }
    friend void counts<TT>();
    friend void report<>(HasFriendT<TT> &);
};

template <typename T>
int HasFriendT<T>::ct = 0;

// template friend functions definitions
template <typename T>
void counts()
{
    cout << "template size: " << sizeof(HasFriendT<T>) << "; ";
    cout << "template counts(): " << HasFriendT<T>::ct << endl;
}

template <typename T>
void report(T & hf)
{
    cout << hf.item << endl;
}

int main()
{
    counts<int>();
    HasFriendT<int> hfi1(10);
    HasFriendT<int> hfi2(20);
    HasFriendT<double> hfdb(10.5);
    report(hfi1);  // generate report(HasFriendT<int> &)
    report(hfi2);  // generate report(HasFriendT<int> &)
    report(hfdb);  // generate report(HasFriendT<double> &)
    cout << "counts<int>() output:\n";
    counts<int>();
    cout << "counts<double>() output:\n";
    counts<double>();
    // std::cin.get();
    return 0; 
}

正如您看到的,counts和 counts报告的模板大小不同,这表明每种 T类型都有自己的友元函数 count( )。

3.模板类的非约束模板友元函数

前一节中的约束模板友元函数是在类外面声明的模板的具体化。int 类具体化获得int 函数具体化,依此类推。通过在类内部声明模板,可以创建非约束友元函数,即每个函数具体化都是每个类具体化的友元。对于非约束友元,友元模板类型参数与模板类类型参数是不同的:

template <typename T>
class ManyFriend
template <typename C,typename D> friend void show2(C &, D &);

程序清单 14.24是一个使用非约束友元的例子。其中,函数调用show2(hfl,hf2)与下面的具体化匹配:

void show2<ManyFriend<int>&,ManyFriend<int>&>(ManyFriend<int>&c,ManyFriend<int>&d);

因为它是所有ManyFriend具体化的友元,所以能够访问所有具体化的item成员,但它只访问了ManyFriend对象。
同样,show2(hfd,hf2)与下面具体化匹配:

void show2<ManyFriend<double>&,ManyFriend<int> &>(ManyFriend<double>&c,ManyFriend<int>&d);

它也是所有 ManyFriend 具体化的友元,并访问了ManyFriend对象的item 成员和 ManyFriend对象的 item 成员。

程序清单14.24 manyfrnd.cpp

// manyfrnd.cpp -- unbound template friend to a template class
#include <iostream>
using std::cout;
using std::endl;

template <typename T>
class ManyFriend
{
private:
    T item;
public:
    ManyFriend(const T & i) : item(i) {}
    template <typename C, typename D> friend void show2(C &, D &);
};

template <typename C, typename D> void show2(C & c, D & d)
{
    cout << c.item << ", " << d.item << endl;
}

int main()
{
    ManyFriend<int> hfi1(10);
    ManyFriend<int> hfi2(20);
    ManyFriend<double> hfdb(10.5);
    cout << "hfi1, hfi2: ";
    show2(hfi1, hfi2);
    cout << "hfdb, hfi2: ";
    show2(hfdb, hfi2);
    // std::cin.get();
    return 0;
}

标签:友元,14.4,void,HasFriendT,C++,template,具体化,模板
From: https://blog.csdn.net/zhyjhacker/article/details/140088416

相关文章

  • C++11新特性
    1.字符串原始字面量        在C++11中添加了定义原始字符串的字面量,定义方式为:R“xxx(原始字符串)xxx”其中()两边的字符串可以省略。原始字面量R可以直接表示字符串的实际含义,而不需要额外对字符串做转义或连接等操作。        比如:编程过程中,使用的字符串中......
  • C++11 mem_fn成员指针包装器
    C++11mem_fn成员指针包装器介绍函数模板std::mem_fn生成成员指针的包装器对象,用于存储、复制及调用成员指针。指向对象的引用和指针(包括智能指针)都可以在调用std::mem_fn时使用。注意:std::mem_fn只能包装public的成员指针,不能包装全局函数这里的成员指针指的是成员......
  • C++基础语法——《循环结构》题解
    循环结构参考资料:https://blog.csdn.net/m0_56945138/article/details/118929416需要掌握:1.for循环用法2.while循环用法3.continue跳过和break终止题号题目名称题解链接3067输出范围内的整数https://www.cnblogs.com/jyssh/p/182740551206简单的累加https://www......
  • 【C++】三只小猪称体重
    基于“黑马程序员”视频有关c++学习(p1-p27)完成本节案例学习入口:https://www.bilibili.com/video/BV1et411b73Z?p=28&vd_source=02cd0dc9bea072ad5e681a740632d7a0题目:有三只小猪称体重,分别输入三只小猪的体重,看一下谁最重?分析:先比较任意两只小猪(A)、(B)    如果A......
  • C++ : 如何用C语言实现C++的虚函数机制?
    前言在 googletest的源码中,看到gtest-matchers.h中实现的MatcherBase 类自定义了一个VTable,这种设计实现了一种类似于C++虚函数的机制。C++中的虚函数机制实质上就是通过这种方式实现的,本文用c语言自定义虚函数表VTable实现了一下virtual的功能,来深刻理解其机制。我们通过创......
  • c++高精度计算-大整数相乘
    例题-信奥赛1307:【例1.3】高精度乘法题目描述:输入两个高精度正整数M和N(M和N均小于100位)。求这两个高精度数的积。输入:输入两个高精度正整数M和N。输出:求这两个高精度数的积。输入样例:363输出样例:108 做题思路:学习乘法的朋友大概对加减法都有一定的了解,我就......
  • 【保姆级教程+配置源码】在VScode配置C/C++环境
    目录一、下载VScode1.在官网直接下载安装即可2.安装中文插件二、下载C语言编译器MinGW-W64三、配置编译器环境变量1.解压下载的压缩包,复制该文件夹下bin目录所在地址2.在电脑搜索环境变量并打开3.点击环境变量→选择系统变量里的Path→点击编辑按钮4.点击新建5......
  • item7 Moving to Modern C++**
    第3章移步现代C++CHAPTER3MovingtoModernC++说起知名的特性,C++11/14有一大堆可以吹的东西,auto,智能指针(smartpointer),移动语义(movesemantics),lambda,并发(concurrency)——每个都是如此的重要,这章将覆盖这些内容。掌握这些特性是必要的,要想成为高效率的现代C++程序员需......
  • 【C++】 ——【模板初阶】——基础详解
    目录1.泛型编程1.1泛型编程的概念1.2泛型编程的历史与发展1.3泛型编程的优势1.4泛型编程的挑战2.函数模板2.1函数模板概念2.2函数模板格式2.3函数模板的原理2.4函数模板的实例化2.5模板参数的匹配原则2.6函数模板的特化2.7函数模板的使用注意事项2.......
  • NzN的C++之路--拷贝构造函数&&赋值运算符重载
    目录Part1拷贝构造函数一、概念二、特征Part2赋值运算符重载一、运算符重载二、赋值运算符重载三、前置++和后置++重载Part3const成员Part4 取地址及const取地址操作符重载 Part1拷贝构造函数一、概念        拷贝构造函数:只有单个形参,该形参......