C++ Primer Plus 学习笔记 成员模板 模板用作参数 模板友元 模板别名

意思就是类模板中吧类模板当做成员函数或者类成员

直接上代码吧

#include <iostream>
using std::cout;
using std::cin;
using std::endl;
template<typename T>
class beta
{
  private:
    template <typename V>
    class hold
    {
      private:
        V val;
      public:
        shold(V v = 0) : val(v) {}
        void show() const {cout << val << endl;}
        V Value() const {return val;}
    };
    hold<T> q;
    hold<int> n;
  public:
    beta(T t, int i) : q(t), n(i) {}
    template<typename U>
    U blab(U u, T t){return (n.Value() + q.Value()) * u /t;}
    void Show() const { q.show(); n.show();}
};

int main()
{
  beta<double> guy(3.5, 3);
  cout << "T was set to double\n";
  guy.Show();
  cout << "V was set to T, which is double, then V was set to int\n";
  cout << guy.blab(10, 2.3) << endl;
  cout << "U was set to int\n";
  cout << guy.blab(10.0, 2.3) << endl;
  cout << "U was set to double\n";
  cout << "Done\n";
  return 0;
}

C++允许外部定义成员模板。但不是所有的编译器都支持。 如果不支持的话就算了 支持的话可以这么写:

将模板用于参数:

先上代码在说话

stacktp.h

#ifndef STACKTP_H_
#define STACKTP_H_

template<class Type>
class Stack
{
  private:
    enum {MAX = 10};
    Type items[MAX];
    int top;
  public:
    Stack();
    bool isempty();
    bool isfull();
    bool push(const Type & item);
    bool pop(Type & item);
};

template<class Type>
Stack<Type>::Stack()
{
  top = 0;
}

template<class Type>
bool Stack<Type>::isempty()
{
  return top == 0;
}

template<class Type>
bool Stack<Type>::isfull()
{
  return top == MAX;
}

template<class Type>
bool Stack<Type>::push(const Type & item)
{
  if (top < MAX)
  {
    items[top++] = item;
    return true;
  }
  else
  {
    return false;
  }
}

template<class Type>
bool Stack<Type>::pop(Type & item)
{
  if (top > 0)
  {
    item = items[--top];
    return true;
  }
  else
    return false;
}

#endif

tempparm.cpp

#include <iostream>
#include "stacktp.h"

template <template <typename T> class Thing>
class Crab
{
  private:
    Thing<int> s1;
    Thing<double> s2;
  public:
    Crab() {};
    bool push(int a, double x) {return s1.push(a) && s2.push(x);}
    bool pop(int & a, double & x) {return s1.pop(a) && s2.pop(x);}
};

int main() {
  using std::cout;
  using std::cin;
  using std::endl;
// 这时候 Thing形参就是 模板Stack类型 在默认构造函数的时候就生成int型的Stack模板和double型的Stack模板
  Crab<Stack> nebula;
  int ni;
  double nb;
  cout << "Enter int double pairs, such as 4 3.5 (0 0 to end):\n";
  while(cin >> ni >> nb && ni > 0 && nb > 0)
  {
    if (!nebula.push(ni, nb))
      break;
  }
  while (nebula.pop(ni, nb))
    cout << ni << ", " <<nb << endl;
  cout << "Done.\n";
  
  return 0;
}

运行结果:

模板类和友元:

模板类可以有友元, 但是有3种友元

1. 非模板友元

2. 约束模板友元

3.非约束模板友元

 

一个一个来

非模板友元

template <class T>
class A
{
    public:
        friend void counts();
}

counts()是模板所有实例化对象的友元。 这是不带参数的例子。它可以访问全局对象,可以使用全局指针访问的费全局对象。可以创建自己的对象。 可以访问独立于对象的模板类的静态数据成员。

那如果要带参数呢  而且是要带模板类参数呢?

但需要指明特定类型的对象 比如:

template <class T>
class A
{
    public:
        friend void counts(A<T> &);
}

这样将counts将称为A<T>类的友元。

程序示例:

#include <iostream>
using std::cout;
using std::endl;

template <typename T>
class HasFriend
{
  private:
    T item;
    static int ct;
  public:
    HasFriend(const T & i) : item(i) {ct++;}
    ~HasFriend() {ct--;}
    friend void counts();
    friend void reports(HasFriend<T> &);
};

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

void counts()
{
  cout << "int count: " << HasFriend<int>::ct << "; ";
  cout << "double count: " << HasFriend<double>::ct << endl;
}

void reports(HasFriend<int> & hf)
{
  cout << "HasFriend<int>: " << hf.item << endl;
}

void reports(HasFriend<double> & hf)
{
  cout << "HasFriend<double>: " << hf.item << endl;
}

int main()
{
  cout << "No objects delared: ";
  counts();
  HasFriend<int> hfi1(10);
  cout << "After hfil declared: ";
  counts();
  HasFriend<int> hfi2(20);
  cout << "After hfi2 declared: ";
  counts();
  HasFriend<double> hfdb(10.5);
  cout << "AFter hfdb delared: ";
  counts();
  reports(hfi1);
  reports(hfi2);
  reports(hfdb);

  return 0;
}

运行结果

2.约束模板友元函数

就是把友元函数先声明为函数模板 然后在类模板中定义的是该函数模板

程序示例:

#include <iostream>
using std::cout;
using std::endl;

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

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<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);
  report(hfi2);
  report(hfdb);
  cout << "counts<int>() output:\n";
  counts<int>();
  cout << "counts<double>() output:\n";
  counts<double>();

  return 0;
}

运行结果

3.非约束模板友元函数

模板类型放开 ,不用跟着模板类型走:

示例:

#include <iostream>
using std::cout;
using std::cin;

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 << '\n';
}

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);

  return 0;
}

运行结果

大体区别就是

非模板的友元: 没有跟着哪个类 就是跟某个实例对象友元。

约束模板函数: 就是跟某个类型的模板关联。 

非约束模板函数: 不限制某个类型的模板, 因为定义了另外的两个模板参数。所以可以传入不同类型的模板作为参数。

然后目前来说。好像没啥卵用。

模板别名:

可以这样定义别名:

typedef std::array<int, 12> arri;

C++11 可以这样:

template<typename T> 

using arrtype = std::array<T, 12>;

然后可以这么干:

arrtype<double> gallons;

arrtype<int> days;   == array<int , 12>

这种定义别名的方式也适用于非模板

优点: 可读性更强,因为它让类型名和类型信息更清晰。

总结:

第十四章 真 •  完结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@凌晨三点半

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值