C++ 类模板之类外实现重载运算符和友元函数

部署运行你感兴趣的模型镜像

在同一个CPP中,使用友元函数,同时在类外实现,这里.h .cpp未分离,如果分离写法不一样。
一般在使用类模板时,将声明和实现放在同一文件中,可命名为.hpp后缀,即.h .cpp在同一文件中

1.重载操作符

定义一个类,通过重载<< 打印输出该类的成员;

方法1,、
在类中声明该函数,同时前面加上 template <class T1, class T2>

  template <class T1, class T2>
  friend std::ostream&  operator<<(std::ostream& os, Person<T1, T2>& p);

方法2:
1)类内写完frien语句后,需要在类外声明本类并且声明友元函数。
2)在friend的语句中加上<>。

//在类外进行前置声明
template <class T1, class T2> std::ostream& operator<<(std::ostream& os, Person<T1, T2>& p);friend的语句中 << 后 加上<T1,T2>
 friend std::ostream& operator<<<T1,T2>(std::ostream& os, Person<T1, T2>& p);

完整程序如下:

#include <iostream>
using namespace std;

//在类外进行前置声明

// 友元函数在类外面实现,并且都在同一个CPP文件中,
//需要在前面对类和对应操作符重载函数进行前置声明。
// 同时在类内部声明的对应函数需要在参数链表前加入 "<T>"。
template <class T1, class T2> class Person;
template <class T1, class T2> std::ostream& operator<<(std::ostream& os, Person<T1, T2>& p);

//类模板 类外实现
//类模板
template <class T1, class T2> 
class Person {
public:
  //模板类中使用友元
  //重载左移操作符,用于直接打印输出
  //方法1
  //template <class T1, class T2>  //定要加 这句,不过这样的写法在linux不能通过
  //friend std::ostream&  operator<<(std::ostream& os, Person<T1, T2>& p);
  
  //方法2在操作符后加 <T1,T2>,同时进行类前置声明
  //方法1 在VS中可以便宜,但 要在Linux下会出错
  friend std::ostream& operator<<<T1,T2>(std::ostream& os, Person<T1, T2>& p);
  Person(T1 id, T2 age);
  void showPerson();

private:
  T1 mId_;
  T2 mAge_;
};

//声明和实现分开时,我们需要对函数的声明做特殊处理,
//注意,这里类名应是Person<T1,T2>
template <class T1, class T2> 
Person<T1, T2>::Person(T1 id, T2 age) {
  this->mAge_ = age;
  this->mId_ = id;
}

template <class T1, class T2> void Person<T1, T2>::showPerson() {
  std::cout << "id.....:" << mId_ << ",age:" << mAge_ << std::endl;
}


//通过重载左移操作符,用于直接打印输出
template <class T1, class T2>
std::ostream& operator<<(std::ostream& os, Person<T1, T2>& p) {
  std::cout << "operator---  id: " << p.mId_ << ",age:" << p.mAge_ << std::endl;
  return os;
}


//类模板在类外实现时,不要滥用友元
void testShow() {
  //函数模板在调用时,可以自动进行类型推导
  //类模板必须显式声明
  Person<int, int> person(12, 11111);
  //person.showPerson();
  std::cout << "ddd: " << person << std::endl;
}

int main() {
  testShow();
  return 0;
}

2.使用普通友元函数

使用普通友元函数与上面的操作符重载,是同样的操作方法,
完成程序如下:

#include <iostream>
using namespace std;

//方法2  在类外进行前置声明
template <class T1, class T2> class Person;
template <class T1, class T2> std::ostream& operator<<(std::ostream& os, Person<T1, T2>& p);


//类模板 类外实现
//类模板
template <class T1, class T2> 
class Person {
public:
  //使用普通友元函数进行类外输出
  
  //方法1
  //template <class T1, class T2>
  //friend void printPerson(Person<T1, T2>& p);
  
  //方法2
  //应推荐的写法,把类进行前置声明
  friend void printPerson<T1,T2>(Person<T1, T2>& p);

  Person(T1 id, T2 age);
  void showPerson();

private:
  T1 mId_;
  T2 mAge_;
};

//声明和实现分开时,我们需要对函数的声明做特殊处理,
//注意,这里类名应是Person<T1,T2>
template <class T1, class T2> 
Person<T1, T2>::Person(T1 id, T2 age) {
  this->mAge_ = age;
  this->mId_ = id;
}

template <class T1, class T2> void
 Person<T1, T2>::showPerson() {
  std::cout << "id.....:" << mId_ << ",age:" << mAge_ << std::endl;
}


template <class T1, class T2>
void printPerson(Person<T1, T2>& p) {
	std::cout << "printPerson, id: " << p.mId_ << ",age:" << p.mAge_ << std::endl;

}
//类模板在类外实现时,不要滥用友元
void testShow() {
  //函数模板在调用时,可以自动进行类型推导
  //类模板必须显式声明
  Person<int, int> person(12, 11111);
  printPerson(person);
}

int main() {
  testShow();
  return 0;
}

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值