第八层:模板(下)

简介: 第八层:模板(下)

代码验证:


#include<iostream>
using namespace std;
class A1
{
public:
  void print1()
  {
  cout << "A1在被调用" << endl;
  }
};
class A2
{
public:
  void print2()
  {
  cout << "A2在被调用" << endl;
  }
};
template<class T>
class A
{
public:
  void print1()
  {
  T a;
  a.print1();
  }
  void print2()
  {
  T a.print2();
  }
};
void test1()
{
  A<A1> a;
  a.print1();
  a.print2();
}
int main()
{
  test1();
  return 0;
}

0a2653c851af460fa595bd959398a8f1.png

代码在没有运行的时候,没有报错,在运行之后,会发现内部编译错误,是因为通用类型被定义为A1,A1中没有print2函数,现在注释掉,在来看看:


#include<iostream>
using namespace std;
class A1
{
public:
  void print1()
  {
  cout << "A1在被调用" << endl;
  }
};
class A2
{
public:
  void print2()
  {
  cout << "A2在被调用" << endl;
  }
};
template<class T>
class A
{
public:
  void print1()
  {
  T a;
  a.print1();
  }
  //void print2()
  //{
  //  T a.print2();
  //}
};
void test1()
{
  A<A1> a;
  a.print1();
  //a.print2();
}
int main()
{
  test1();
  return 0;
}

0eacb84100b54626af849e6b562bf92a.png

可以调用,这就是因为在确定通用类型之前没有生成内部函数,在确定好之后,会创建成员函数。


类模板对象做函数参数


类模板实例化出来的对象,可以做函数的参数吗?可以而且方法还不少:

1.指定传入类型:直接显示对象的数据类型

2.参数模板化:将对象中的参数变成模板进行传递

3.整个类模板化:将整个对象模型模板化进行传递


指定传入类型


指定传入类型怎么去做?下面用代码来演示:


#include<string>
#include<iostream>
using namespace std;
template<class T1,class T2>
class per
{
public:
  per(T1 a, T2 b)
  {
  _name = a;
  _age = b;
  }
  T1 _name;
  T2 _age;
};
void print(per<string, int> p)
{
  cout << p._name << "的年龄" << p._age << "岁" << endl;
}
void test1()
{
  per<string, int> p("张三",18);
  print(p);
}
int main()
{
  test1();
  return 0;
}

0a2653c851af460fa595bd959398a8f1.png

直接将对象名前面的类名和模板的数据类型传过去就可以。


参数模板化


参数模板化,顾名思义,就是将参数变成和模板一样,模板有什么特点?通用的数据类型,就其实就是将模板的参数列表变成通用的数据类型即可:


#include<string>
#include<iostream>
using namespace std;
template<class T1,class T2>
class per
{
public:
  per(T1 a, T2 b)
  {
  _name = a;
  _age = b;
  }
  T1 _name;
  T2 _age;
};
template<class T1,class T2>
void print(per<T1,T2> p)
{
  cout << p._name << "的年龄" << p._age << "岁" << endl;
}
void test1()
{
  per<string, int> p("张三",18);
  print(p);
}
int main()
{
  test1();
  return 0;
}

0eacb84100b54626af849e6b562bf92a.png


将对象模型进行模板化


将对象模型进行模板化,就是将对象变成一个通用类型:


#include<string>
#include<iostream>
using namespace std;
template<class T1,class T2>
class per
{
public:
  per(T1 a, T2 b)
  {
  _name = a;
  _age = b;
  }
  T1 _name;
  T2 _age;
};
template<class T>
void print(T p)
{
  cout << p._name << "的年龄" << p._age << "岁" << endl;
}
void test1()
{
  per<string, int> p("张三",18);
  print(p);
}
int main()
{
  test1();
  return 0;
}

2d65d23f6d4748949b924e4057485923.png


类模板和继承


既然都是类,那类模板可以作为父类吗?被继承吗?是可以的,但是有需要注意的地方:


1.当子类继承的父类是一个类模板的时候,子类在声明的时候,要指出父类中通用类型的类型

2.如果不指定,编译器无法给子类分配内存

3.如果想灵活的指出父类中通用类型的类型,子类也需要变成类模板


第一点和第二点


因为在子类中会继承父类中的所有非静态成员变量,这个时候如果不知道父类中成员是什么类型,则编译器不知道应该分配多少内存给子类当中,所以要指定出来,那怎么指定呢?写法:

class 子类 : 继承方式 父类< 指定出类型 >

代码验证:


#include<iostream>
using namespace std;
template<class T1,class T2>
class per
{
public:
  per(T1 a, T2 b)
  {
  _name = a;
  _age = b;
  }
  T1 _name;
  T2 _age;
};
class per1 :public per
{
public:
};
int main()
{
  return 0;
}

2d65d23f6d4748949b924e4057485923.png

这个时候没有写,报错。


#include<string>
#include<iostream>
using namespace std;
template<class T1,class T2>
class per
{
public:
  per(T1 a, T2 b)
  {
  _name = a;
  _age = b;
  }
  T1 _name;
  T2 _age;
};
class per1 :public per<string ,int>
{
public:
};
int main()
{
  return 0;
}

2e9b90b2ca334476abebe75bafe6eeaa.png

写上之后不报错。


灵活指出父类中的类型


那怎么样才能灵活的指出呢?这个时候将子类变成模板即可:


#include<string>
#include<iostream>
using namespace std;
template<class T1,class T2>
class per
{
public:
  per(T1 a, T2 b)
  {
  _name = a;
  _age = b;
  }
  T1 _name;
  T2 _age;
};
template<class T,class T1>
class per1 :public per<T,T1>
{
public:
};
int main()
{
  return 0;
}

0a2653c851af460fa595bd959398a8f1.png

这个时候,这个T和T1就指向的是父类中的两个通用模板:

0eacb84100b54626af849e6b562bf92a.png


类模板成员函数类外实现


普通类的成员函数可以在类外实现,那类模板的是否可以?是可以的,有一定的语法格式,不仅仅要加作用域:

template < class T >

返回类型 类名< 参数 >:: 函数名 (T ____)

构造函数也可以进行类外实现,用代码验证一下:


#include<string>
#include<iostream>
using namespace std;
template<class T1,class T2>
class per
{
public:
  per(T1 a, T2 b);
  T1 _name;
  T2 _age;
};
template<class T1,class T2>
per<T1, T2>::per(T1 a, T2 b)
{
  _name = a;
  _age = b;
  cout << _name << "的年龄为" << _age << endl;
}
void test1()
{
  per<string, int>p("张三", 18);
}
int main()
{
  test1();
  return 0;
}

0a2653c851af460fa595bd959398a8f1.png


类模板的分文件编写


当代码量过大时,程序员通常会选择分文件编写,将声明实现和调用分开,那模板分开可以正常使用吗?

验证:


test.cpp

#include"per.h"
void test1()
{
  per<string, int>p("张三", 18);
}
int main()
{
  test1();
  return 0;
}

per.cpp

#include"per.h"
template<class T1, class T2>
class per
{
public:
  per(T1 a, T2 b)
  {
  _name = a;
  _age = b;
  cout << _name << "的年龄为" << _age << endl;
  }
  T1 _name;
  T2 _age;
};


per.h

#pragma once
#include<string>
#include<iostream>
using namespace std;
template<class T1, class T2>
class per;

0eacb84100b54626af849e6b562bf92a.png

是报错的,那这是为什么?上面说到,对于类模板中的成员函数在编译器阶段才去创建的,我们包含的头文件,那这个时候编译器就不会看到实现部分,只看到了声明,那这个时候可以将引的头文件该成实现的模块:


#include"per.cpp"
void test1()
{
  per<string, int>p("张三", 18);
}
int main()
{
  test1();
  return 0;
}

0a2653c851af460fa595bd959398a8f1.png

是可以正常使用的,那这个时候还可以将声明和实现放在一起,任何将后缀改为hpp,其他也可以,只是hpp是约定俗成的,一看上去就知道是模板的实现和定义。


类模板和友元


那类模板可以有友元函数吗?是可以拥有的,分为类内实现和类外实现


类内实现


类内实现直接在类捏将函数功能实现出来即可:


template<class T1,class T2>
class per
{
  friend void print(per<T1, T2> &p)
  {
  cout << _name << "的年龄为" << _age << endl;
  }
public:
  per(T1 a, T2 b)
  {
  _name = a;
  _age = b;
  }
private:
  string _name;
  int _age;
};


类外实现


template<class T1,class T2>
class per
{
  friend void print< >(per<T1, T2>& p);
public:
  per(T1 a, T2 b)
  {
  _name = a;
  _age = b;
  }
private:
  string _name;
  int _age;
};


类外实现时要注意,需要提前让编译器知道它存在,所以声明在类模板中。


注意


掌握模板不是为了写模板,而是为了使用第九层中的stl。


第九层…顶层?


看完上面的内容,我便踏入了前往第九层的楼梯,上来之后,抬头便是许久未见的天空…


相关文章
|
17天前
|
人工智能 数据可视化 安全
王炸组合!阿里云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!(附带免费使用6个月服务器)
本文详解如何用阿里云Lighthouse一键部署OpenClaw,结合飞书CLI等工具,让AI真正“动手”——自动群发、生成科研日报、整理知识库。核心理念:未来软件应为AI而生,CLI即AI的“手脚”,实现高效、安全、可控的智能自动化。
34818 45
王炸组合!阿里云 OpenClaw X 飞书 CLI,开启 Agent 基建狂潮!(附带免费使用6个月服务器)
|
11天前
|
人工智能 自然语言处理 安全
Claude Code 全攻略:命令大全 + 实战工作流(建议收藏)
本文介绍了Claude Code终端AI助手的使用指南,主要内容包括:1)常用命令如版本查看、项目启动和更新;2)三种工作模式切换及界面说明;3)核心功能指令速查表,包含初始化、压缩对话、清除历史等操作;4)详细解析了/init、/help、/clear、/compact、/memory等关键命令的使用场景和语法。文章通过丰富的界面截图和场景示例,帮助开发者快速掌握如何通过命令行和交互界面高效使用Claude Code进行项目开发,特别强调了CLAUDE.md文件作为项目知识库的核心作用。
10885 36
Claude Code 全攻略:命令大全 + 实战工作流(建议收藏)
|
7天前
|
人工智能 JavaScript Ubuntu
低成本搭建AIP自动化写作系统:Hermes保姆级使用教程,长文和逐步实操贴图
我带着怀疑的态度,深度使用了几天,聚焦微信公众号AIP自动化写作场景,写出来的几篇文章,几乎没有什么修改,至少合乎我本人的意愿,而且排版风格,也越来越完善,同样是起码过得了我自己这一关。 这个其实OpenClaw早可以实现了,但是目前我觉得最大的区别是,Hermes会自主总结提炼,并更新你的写作技能。 相信就冲这一点,就值得一试。 这篇帖子主要就Hermes部署使用,作一个非常详细的介绍,几乎一步一贴图。 关于Hermes,无论你赞成哪种声音,我希望都是你自己动手行动过,发自内心的选择!
2290 22
|
29天前
|
人工智能 JSON 机器人
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
本文带你零成本玩转OpenClaw:学生认证白嫖6个月阿里云服务器,手把手配置飞书机器人、接入免费/高性价比AI模型(NVIDIA/通义),并打造微信公众号“全自动分身”——实时抓热榜、AI选题拆解、一键发布草稿,5分钟完成热点→文章全流程!
45721 156
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
|
11天前
|
机器学习/深度学习 存储 人工智能
还在手写Skill?hermes-agent 让 Agent 自己进化能力
Hermes-agent 是 GitHub 23k+ Star 的开源项目,突破传统 Agent 依赖人工编写Aegnt Skill 的瓶颈,首创“自我进化”机制:通过失败→反思→自动生成技能→持续优化的闭环,让 Agent 在实践中自主构建、更新技能库,持续自我改进。
1735 6
|
5天前
|
人工智能 弹性计算 安全
Hermes Agent是什么?怎么部署?超详细实操教程
Hermes Agent 是 Nous Research 于2026年2月开源的自进化AI智能体,支持跨会话持久记忆、自动提炼可复用技能、多平台接入与200+模型切换,真正实现“越用越懂你”。MIT协议,部署灵活,隐私可控。
1440 2

热门文章

最新文章

下一篇
开通oss服务