当前位置: 首页 > news >正文

团购机票网站建设网站婚礼服务态网站建设论文

团购机票网站建设,网站婚礼服务态网站建设论文,网站建设公司专业公司排名,织梦做中英文网站步骤目录 前言 类模板语法 类模板和函数模板的区别 类模板没有自动类型推导的使用方式 类模板在模板参数列表中可以有默认参数 类模板中成员函数创建时机 类模板对象做函数参数 指定传入的类型 参数模板化 整个类模板化 类模板与继承 类模板成员函数类外实现 类模板分…

目录

前言

类模板语法

类模板和函数模板的区别

类模板没有自动类型推导的使用方式

类模板在模板参数列表中可以有默认参数

类模板中成员函数创建时机

类模板对象做函数参数

指定传入的类型

参数模板化

整个类模板化

类模板与继承

类模板成员函数类外实现

类模板分文件编写

问题

解决

Demo 

person.hpp

person.cpp 

类模板与友元

全局函数配合友元   类内实现

全局函数配合友元  类外实现

数组类封装

myArray.hpp

myArray.cpp


 

前言

C++中的类模板允许您创建可以适用于多个类型的通用类。类模板是一种将类型参数化的方法,可以根据需要实例化为具体类型的类。

类模板语法

        template<typename T>

        类

  •     template    ---  声明创建模板
  •     typename  --- 表面其后面的符号是一种数据类型,可以用class代替
  •     T                ---   通用的数据类型,名称可以替换,通常为大写字母
  • 模板参数列表可以包含一个或多个类型参数,用逗号分隔。
  • 在类模板定义中,可以使用模板参数作为类成员、函数参数、局部变量的类型等。
  • 类模板的定义通常放在头文件中。
//类模板
template<class NameType, class AgeType>
class Person
{
public:Person(NameType name, AgeType age){this->mName = name;this->mAge = age;}void showPerson(){cout << "name: " << this->mName << " age: " << this->mAge << endl; }
public:NameType mName;AgeType mAge;
};void test01()
{// 指定NameType 为string类型,AgeType 为 int类型Person<string, int>P1("孙悟空", 999);P1.showPerson();
}int main() {test01();return 0;
}

类模板和函数模板的区别

类模板没有自动类型推导的使用方式


#include <string>
//类模板
template<class NameType, class AgeType = int>
class Person
{
public:Person(NameType name, AgeType age){this->mName = name;this->mAge = age;}void showPerson(){cout << "name: " << this->mName << " age: " << this->mAge << endl;}
public:NameType mName;AgeType mAge;
};//1、类模板没有自动类型推导的使用方式
void test01()
{// Person p("孙悟空", 1000); // 错误 类模板使用时候,不可以用自动类型推导Person <string, int>p("孙悟空", 1000); // name: 孙悟空 age: 1000 必须使用显示指定类型的方式,使用类模板 p.showPerson();
}int main() {test01();return 0;
}

类模板在模板参数列表中可以有默认参数

#include <string>
//类模板
template<class NameType, class AgeType = int>
class Person
{
public:Person(NameType name, AgeType age){this->mName = name;this->mAge = age;}void showPerson(){cout << "name: " << this->mName << " age: " << this->mAge << endl;}
public:NameType mName;AgeType mAge;
};//2、类模板在模板参数列表中可以有默认参数
void test02()
{Person <string> p("猪八戒", 999); // name: 猪八戒 age : 999 类模板中的模板参数列表 可以指定默认参数p.showPerson();
}int main() {test02();return 0;
}

类模板中成员函数创建时机

类模板中成员函数和普通类中成员函数创建时机是有区别的:

  • 普通类中的成员函数一开始就可以创建
  • 类模板中的成员函数在调用时才创建

class Person1
{
public:void showPerson1(){cout << "Person1 show" << endl;}
};class Person2
{
public:void showPerson2(){cout << "Person2 show" << endl;}
};template<class T>
class MyClass
{
public:T obj;// 类模板中的成员函数,并不是一开始就创建的,而是在模板调用时再生成void fun1() { obj.showPerson1();}void fun2() { obj.showPerson2();}};void test01()
{MyClass<Person1> m;m.fun1(); // Person1 show//m.fun2(); // 编译会出错,说明函数调用才会去创建成员函数class MyClass<Person2> M;M.fun2(); // Person2 show 正确}int main() {test01();return 0;
}

类模板对象做函数参数

一共有三种传入方式:

  1. 指定传入的类型   --- 直接显示对象的数据类型
  2. 参数模板化       --- 将对象中的参数变为模板进行传递
  3. 整个类模板化     --- 将这个对象类型 模板化进行传递

指定传入的类型

#include <string>
//类模板
template<class NameType, class AgeType = int>
class Person
{
public:Person(NameType name, AgeType age){this->mName = name;this->mAge = age;}void showPerson(){cout << "name: " << this->mName << " age: " << this->mAge << endl;}
public:NameType mName;AgeType mAge;
};//1、指定传入的类型
void printPerson1(class Person<string, int> &p) // class可加可不加
{p.showPerson(); // 孙悟空 100
}
void test01()
{class Person <string, int >p("孙悟空", 100);printPerson1(p);
}int main() {test01();return 0;
}

参数模板化

#include <string>
//类模板
template<class NameType, class AgeType = int>
class Person
{
public:Person(NameType name, AgeType age){this->mName = name;this->mAge = age;}void showPerson(){cout << "name: " << this->mName << " age: " << this->mAge << endl;}
public:NameType mName;AgeType mAge;
};//2、参数模板化
template <class T1, class T2>
void printPerson2(Person<T1, T2>&p)
{p.showPerson(); // 猪八戒 90cout << "T1的类型为: " << typeid(T1).name() << endl; // typeid(T).name 获取泛型类型cout << "T2的类型为: " << typeid(T2).name() << endl;
}
void test02()
{class Person <string, int >p("猪八戒", 90);printPerson2(p);
}int main() {test02();return 0;
}

整个类模板化


#include <string>
//类模板
template<class NameType, class AgeType = int>
class Person
{
public:Person(NameType name, AgeType age){this->mName = name;this->mAge = age;}void showPerson(){cout << "name: " << this->mName << " age: " << this->mAge << endl;}
public:NameType mName;AgeType mAge;
};//3、整个类模板化
template<class T>
void printPerson3(T & p)
{cout << "T的类型为: " << typeid(T).name() << endl;p.showPerson(); // 唐僧 30}
void test03()
{Person <string, int >p("唐僧", 30);printPerson3(p);
}int main() {test03();return 0;
}

类模板与继承

当类模板碰到继承时,需要注意一下几点:

  • 当子类继承的父类是一个类模板时,子类在声明的时候,要指定出父类中T的类型
  • 如果不指定,编译器无法给子类分配内存
  • 如果想灵活指定出父类中T的类型,子类也需变为类模板

template<class T>
class Base
{T m;
};//class Son:public Base  //错误,c++编译需要给子类分配内存,必须知道父类中T的类型才可以向下继承
class Son :public Base<int> //必须指定一个类型,这样的话父类的模板泛型其实也没有了意义,见下方改进
{
};
void test01()
{Son c;
}// 类模板继承类模板 ,可以用T2指定父类中的T类型
template<class T1, class T2>
class Son2 :public Base<T2>
{
public:Son2(){cout << typeid(T1).name() << endl; // intcout << typeid(T2).name() << endl; // char}T1 demo;
};void test02()
{Son2<int, char> child1; // int给了 儿子类的demo成员,char给了父类的T2泛型所执行的成员或变量
}int main() {test01();test02();return 0;
}

类模板成员函数类外实现

类模板中成员函数类外实现时,需要加上模板参数列表 

//类模板中成员函数类外实现
template<class T1, class T2>
class Person {
public://成员函数类内声明Person(T1 name, T2 age);void showPerson();public:T1 m_Name;T2 m_Age;
};// 类模板的构造函数 类外实现
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) {this->m_Name = name;this->m_Age = age;
}// 类模板的成员函数 类外实现
template<class T1, class T2>
void Person<T1, T2>::showPerson() {cout << "姓名: " << this->m_Name << " 年龄:" << this->m_Age << endl;
}void test01()
{Person<string, int> p("Tom", 20);p.showPerson();
}int main() {test01();return 0;
}

类模板分文件编写

问题

类模板的声明和实现分开存放于.h .cpp中,会导致分文件编写时链接不到,因为类模板中成员函数创建时机是在调用阶段,

解决

将类模板声明和实现写到同一个文件中,并更改后缀名为.hpp,hpp是约定的名称 

Demo 

person.hpp

#pragma once
#include <iostream>
using namespace std;
#include <string>template<class T1, class T2>
class Person {
public:Person(T1 name, T2 age);void showPerson();
public:T1 m_Name;T2 m_Age;
};//构造函数 类外实现
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) {this->m_Name = name;this->m_Age = age;
}//成员函数 类外实现
template<class T1, class T2>
void Person<T1, T2>::showPerson() {cout << "姓名: " << this->m_Name << " 年龄:" << this->m_Age << endl; // 在这里哦
}

person.cpp 

#include <iostream>
using namespace std;
// 解决方式2,将声明和实现写到一起,文件后缀名改为.hpp
#include "person.hpp"void test01()
{Person<string, int> p("Tom", 10);p.showPerson(); // 姓名: Tom 年龄:10
}int main() {test01();return 0;
}

类模板与友元

全局函数配合友元   类内实现

template<class T1, class T2>
class Person
{//1、全局函数配合友元   类内实现friend void printPerson(Person<T1, T2> & p){cout << "姓名: " << p.m_Name << " 年龄:" << p.m_Age << endl;}public:Person(T1 name, T2 age){this->m_Name = name;this->m_Age = age;}private:T1 m_Name;T2 m_Age;};//1、全局函数在类内实现
void test01()
{class Person <string, int >p("Tom", 20);printPerson(p);
}int main() {test01(); // 姓名: Tom 年龄:20return 0;
}

全局函数配合友元  类外实现

//2、全局函数配合友元  类外实现 - 先做函数模板声明,下方在做函数模板定义,在做友元
template<class T1, class T2> class Person;//如果声明了函数模板,可以将实现写到后面,否则需要将实现体写到类的前面让编译器提前看到
//template<class T1, class T2> void printPerson2(Person<T1, T2> & p); template<class T1, class T2>
void printPerson2(Person<T1, T2> & p)
{cout << "类外实现 ---- 姓名: " << p.m_Name << " 年龄:" << p.m_Age << endl;
}template<class T1, class T2>
class Person
{// 2.全局函数配合友元  类外实现friend void printPerson2<>(Person<T1, T2> & p);public:Person(T1 name, T2 age){this->m_Name = name;this->m_Age = age;}private:T1 m_Name;T2 m_Age;};//2、全局函数在类外实现
void test02()
{Person <string, int >p("Jerry", 30);printPerson2(p);
}int main() {test02();return 0;
}

数组类封装

myArray.hpp

#pragma once
#include <iostream>
using namespace std;template<class T>
class MyArray
{
public://构造函数MyArray(int capacity){this->m_Capacity = capacity;this->m_Size = 0;pAddress = new T[this->m_Capacity];}//拷贝构造MyArray(const MyArray & arr){this->m_Capacity = arr.m_Capacity;this->m_Size = arr.m_Size;this->pAddress = new T[this->m_Capacity];for (int i = 0; i < this->m_Size; i++){//如果T为对象,而且还包含指针,必须需要重载 = 操作符,因为这个等号不是 构造 而是赋值,// 普通类型可以直接= 但是指针类型需要深拷贝this->pAddress[i] = arr.pAddress[i];}}//重载= 操作符  防止浅拷贝问题MyArray& operator=(const MyArray& myarray) {if (this->pAddress != NULL) {delete[] this->pAddress;this->m_Capacity = 0;this->m_Size = 0;}this->m_Capacity = myarray.m_Capacity;this->m_Size = myarray.m_Size;this->pAddress = new T[this->m_Capacity];for (int i = 0; i < this->m_Size; i++) {this->pAddress[i] = myarray[i];}return *this;}//重载[] 操作符  arr[0]T& operator [](int index){return this->pAddress[index]; //不考虑越界,用户自己去处理}//尾插法void Push_back(const T & val){if (this->m_Capacity == this->m_Size){return;}this->pAddress[this->m_Size] = val;this->m_Size++;}//尾删法void Pop_back(){if (this->m_Size == 0){return;}this->m_Size--;}//获取数组容量int getCapacity(){return this->m_Capacity;}//获取数组大小int	getSize(){return this->m_Size;}//析构~MyArray(){if (this->pAddress != NULL){delete[] this->pAddress;this->pAddress = NULL;this->m_Capacity = 0;this->m_Size = 0;}}private:T * pAddress;  //指向一个堆空间,这个空间存储真正的数据int m_Capacity; //容量int m_Size;   // 大小
};
};

myArray.cpp

#include <iostream>
using namespace std;
#include "myArray.hpp"
#include <string>void printIntArray(MyArray<int>& arr) {for (int i = 0; i < arr.getSize(); i++) {cout << arr[i] << " ";}cout << endl;
}//测试内置数据类型
void test01()
{MyArray<int> array1(10);for (int i = 0; i < 10; i++){array1.Push_back(i);}cout << "array1打印输出:" << endl;printIntArray(array1);cout << "array1的大小:" << array1.getSize() << endl;cout << "array1的容量:" << array1.getCapacity() << endl;cout << "--------------------------" << endl;MyArray<int> array2(array1);array2.Pop_back();cout << "array2打印输出:" << endl;printIntArray(array2);cout << "array2的大小:" << array2.getSize() << endl;cout << "array2的容量:" << array2.getCapacity() << endl;
}//测试自定义数据类型
class Person {
public:Person() {}Person(string name, int age) {this->m_Name = name;this->m_Age = age;}
public:string m_Name;int m_Age;
};void printPersonArray(MyArray<Person>& personArr)
{for (int i = 0; i < personArr.getSize(); i++) {cout << "姓名:" << personArr[i].m_Name << " 年龄: " << personArr[i].m_Age << endl;}}void test02()
{//创建数组MyArray<Person> pArray(10);Person p1("孙悟空", 30);Person p2("韩信", 20);Person p3("妲己", 18);Person p4("王昭君", 15);Person p5("赵云", 24);//插入数据pArray.Push_back(p1);pArray.Push_back(p2);pArray.Push_back(p3);pArray.Push_back(p4);pArray.Push_back(p5);printPersonArray(pArray);cout << "pArray的大小:" << pArray.getSize() << endl;cout << "pArray的容量:" << pArray.getCapacity() << endl;}int main() {//test01();test02();return 0;
}

http://www.yayakq.cn/news/334928/

相关文章:

  • 企业网站建设论文5000网站开发响应式
  • 安卓app制作软件湖南seo推广软件
  • 如何做好电子商务网站开发湘潭网站建设 多少费用磐石网络
  • 白菜网站建设国字型网站建设布局
  • 好的建站平台内衣网站建立
  • 长春网站制作平台wordpress微擎
  • 江苏城乡建设厅网站门窗网站模板
  • 刚出来的新产品怎么推荆州seo技术厂家
  • 共享网站的详细规划企业建网站一般要多少钱
  • 英文建设网站wordpress 会员管理系统
  • 微信公众号 网站开发外包网站开发多少钱
  • 网站开发从哪里学起长沙网站优化效果
  • 演示网站网站建设中通知
  • 多域名指向同一网站东莞市网上注册公司流程
  • 羽毛球赛事2023赛程seo综合
  • 城乡建设部网站甘红刚快速搭建网站2020
  • 做网站前台步骤wordpress插件汉化不全
  • 东营区住房和城乡建设局网站久久建筑网官网平台
  • 网站分站开发计划书wordpress集成dplayer
  • 高端科技产品网站建设服务app开发的公司
  • 有没有给人做简历的网站wordpress 纯代码seo
  • 江苏省品牌专业建设网站wordpress菜单定制
  • 网站英文地图怎么做网站开发快速盈利
  • 网站的设计特点有哪些洛客设计平台
  • 淘宝联盟怎么自己做网站推广建设一个网站需要学习什么
  • 加强校园网站建设网站建设案例步骤
  • 做网站需要哪些流程天美传媒传媒官网免费下载
  • 网站建设技术培训有口皆碑的域名备案加急
  • 网站首页适合vue做吗工业产品设计结构图
  • 百度一下图片识别网站优化 ppt