类模板,多种类型的类模板,自定义类模板,类模板的默认类型,数组的模板实现,友元和类模板,友元函数,类模板与静态变量,类模板与普通类之间互相继承,类模板作为模板参数,类嵌套,类模板嵌套,类包装器
1.第一个最简单的类模板案例
#include "mainwindow.h"
#include <QApplication>
#include <QPushButton>
#include <QLabel>
template<class T>
class run
{
public:
T w;
void show()
{
w.show();
}
void settext()
{
w.setText("A");
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
run<QPushButton> run1;
run1.show();
run1.settext();
return a.exec();
}
2.类模板案例2
#include <iostream>
#include <typeinfo>
using namespace std;
int add(int a,int b)
{
std::cout << "add int\n";
return a + b;
}
double add(double a,double b)
{
std::cout << "add double\n";
return a + b;
}
template<class T>
T add(T a,T b)
{
std::cout << "add T\n";
return a + b;
}
class com1
{
public:
int a;
int b;
int add()
{
return a + b;
}
};
class com2
{
public:
double a;
double b;
double add()
{
return a + b;
}
};
template <class T>
class com
{
public:
T a;
T b;
T add()
{
std::cout << typeid(T).name() << std::endl;
return a + b;
}
};
int main()
{
com<double> comx;
comx.a = 19;
comx.b = 29.8;
std::cout << comx.add() << std::endl; //结果四48.8
com2 com21;
com21.a = 10;
com21.b = 20.9;
std::cout << com21.add() << std::endl; //结果是30.9
return 0;
}
多种类型的类模板
案例:
#include<iostream>
#include<string>
//定义两种数据类型的类模板
//STL数据结构,算法,适合任何类型
//定义两种数据类型的类模板
template<class T1,class T2>
class myclass
{
public:
T1 t11;
T2 t22;
myclass(T1 t111, T2 t222) :t11(t111), t22(t222)
{
}
void print()
{
std::cout << t11 << " " << t22 << std::endl;
}
};
void main()
{
myclass<int, double> my1(10, 20.8);
my1.print();
myclass<double, std::string> my2(20.8, "123456abc");
my2.print();
std::cin.get();
}
3.自定义类模板,类模板的默认类型
myArray.h
#pragma once //只包含一次,只是针对VS下的
//类模板可以有一个默认的值
template<class T = int>
class myArray
{
public:
myArray();
~myArray();
};
myArray.cpp
#include "myArray.h"
template <class T = int>//每一个函数都需要加上一个默认的值
myArray<T>::myArray() //类模板成员函数在外部,需要加载类型初始化
{
std::cout << "构造" << typeid(T).name() << std::endl;
}
template <class T = int>
myArray<T>::~myArray()
{
std::cout << "销毁" << typeid(T).name() << std::endl;
}
main.cpp
#include <iostream>
#include <array>
#include <string>
#include "myArray.h"
#include "myArray.cpp" //类模板的成员函数没有实例化,不会自动找到,需要手动包含
using namespace std;
void main1()
{
myArray<double> my1;
myArray<> my2;//C++11的新功能(如果有默认类型了,这时候类型可以为空)
std::cin.get();
//结果输出
//构造double
//构造int
}
void main()
{
array<string, 5>strarray = { "calc", "mspaint", "notepad", "tasklist", "pause" };
for (int i = 0; i < strarray.size();i++)
{
std::cout << strarray[i].c_str() << std::endl;
}
std::cin.get();
//运行结果是:
//calc
//mspaint
//notepad
//tasklist
//pause
}
4.数组的模板实现(类似c++中array的功能)
Array.h
#pragma once
template<class T,int n>
class Array
{
public:
Array();
Array(int length);
~Array();
int size();
T get(int num);
T & operator [](int num);//重载[]
void set(T data, int num);
public:
T *pt;
};
Array.cpp
#include "Array.h"
template<class T, int n>//int n不可以修改,不是类的内部成员
Array<T,n>::Array()
{
this->pt = new T[n];
}
/*****************************
*初始化length个长度的数组
*****************************/
template<class T, int n> //每一个函数都必须模板
Array<T, n>::Array(int length)
{
this->pt = new T[length];
}
/*****************************
*析构数组
*****************************/
template<class T, int n>//每一个函数都必须模板
Array<T, n>::~Array()
{
//n = 0;
delete[] this->pt;
}
/*****************************
*获得Array的大小
*****************************/
template<class T,int n>
int Array<T, n>::size()
{
return n;
}
/*****************************
*获得第n个元素
*****************************/
template<class T, int n>//每一个函数都必须模板
T Array<T, n>::get(int num)//num是数组的下标
{
if (num >= n || num < 0)//报错
{
//异常
}
else
{
return *(this->pt + num);
}
}
/*****************************
*设置第i个元素的值
*****************************/
template<class T,int n> //每一个函数都必须模板
void Array<T, n>::set(T data,int num)
{
if (num < 0 || num >= n)
{
}
else
{
*(pt + num) = data;
}
}
/*****************************
*重载[]
*****************************/
template<class T, int n>//每一个函数都必须模板
T& Array<T, n>::operator [](int num)
{
if (num < 0 || num >= n)
{
}
else
{
return *(pt + num);
}
}
测试Array的主函数:
#include <iostream>
#include <string>
#include "Array.h"
#include "Array.cpp"
using namespace std;
void main1()
{
Array<int, 5> myarray;
for (int i = 0; i < myarray.size(); i++)
{
//设置第i个元素的值为i
myarray.set(i,i);
std::cout << myarray[i] << std::endl;
}
std::cin.get();
//打印结果是:
//0
//1
//2
//3
//4
}
/************************************
*通过函数模板实现打印Array中的元素
************************************/
template<class T,int n> //类模板作为参数,类型无比明确
void print(Array<T, n> &myArray)
{
for (int i = 0; i < myArray.size();i++)
{
std::cout << myArray[i] << std::endl;
}
}
void main()
{
Array<int, 5> myarray;
//调用size()函数,求Array中的大小
for (int i = 0; i < myarray.size();i++)
{
myarray.set(i,i);
}
//通过函数模板实现打印array中的数据
print(myarray);
std::cin.get();
//打印结果是:
//0
//1
//2
//3
//4
}
5.友元类类模板
#include<iostream>
//友元类必须声明类的存在,
//需要声明友元类,必须要与类型相关
template<class T> class myclass;
template<class T> class runclass;
template<class T>
class myclass
{
public:
myclass(T t) :x(t){}
friend class runclass<T>;//声明友元类
private:
T x;//模板友元类
};
template<class T>
class runclass
{
public:
void print(const myclass<T> & my)
{
//直接访问传递进来的类的私有变量
std::cout << my.x << std::endl;
}
};
void main()
{
myclass<double> my1(19.8);
//myclass中定义的友元类
runclass<double> run1;
run1.print(my1);
std::cin.get();
}
6.友元函数
#include<iostream>
template <class T> class myclass; //这里一定要声明这个友元类
template <class T> void printA(myclass<T> my);
template <class T>
class myclass
{
public:
myclass(T t) :x(t)
{
}
friend void print(myclass<T> my)
{
std::cout << my.x << std::endl;
}
//友元函数如果在外部,第一声明要加类型T
//必须要声明类还有函数
friend void printA<T>(myclass<T> my);
private:
T x; //模板友元类
//int y;访问与T无关的类型,普通友元类
};
template <class T>
void printA(myclass<T> my)
{
std::cout << my.x << std::endl;
}
void main()
{
myclass<int> my1(10);
myclass<double> my2(10.9);
printA(my1);
print(my2);
std::cin.get();
//运行结果:
//10
//10.9
}
7.类模板与静态变量,同种类型的实例共享同一个静态变量,不同类的不共享同一个变量
案例:
#include <iostream>
#include<string>
//类模板的static成员,对象,类名《类型》
//不同类型的静态成员变量,地址不一样
//相同类型的静态成员变量,地址一样
template<class T>
class myclass
{
static int data;
public:
static int num;//声明
T a;
myclass(T t) :a(t)
{
num++;
data++;
}
static void run()
{
//this->a;
std::cout << data << std::endl;
std::cout << typeid(T).name() << "\n";
}
};
template<class T>
int myclass<T>::num = 0;
template<class T>
int myclass<T>::data = 0;
//静态变量,静态函数,同种类型的时候共享的静态变量
//类型不同,不共享静态变量
void main1()
{
myclass<int> my1(10);
myclass<double> my2(10.9);
myclass<int> my4(10);
myclass<int>::run();
myclass<int>::run();
myclass<int>::run();
my1.run();
myclass<double>::run();
std::cin.get();
//运行结果:
//2
//int
//2
//int
//2
//int
//1
//double
}
void main()
{
myclass<int > my1(10);
myclass<double > my2(10.9);
myclass<std::string > my3("1234");
myclass<int > my4(10);
std::cout << &my1.num << std::endl;
std::cout << &my2.num << std::endl;
std::cout << &my3.num << std::endl;
std::cout << &my4.num << std::endl;
std::cout << &myclass<int >::num << std::endl;
std::cout << &myclass<float >::num << std::endl;
std::cin.get();
}
8.类模板之间的继承
#include<iostream>
#include <string>
//模板类之间的继承
//类模板可以直接继承类模板,类型必须传递
//普通类继承类模板,需要明确类型实例化类模板
//类模板继承普通类,常规的操作方式
//类模板当作普通哦类,需要模板参数对类进行实例化
template<class T> //抽象模板类
class myclass
{
public:
T x;
myclass(T t) :x(t)
{
}
virtual void print() = 0;
};
template<class T>
class newclass :public myclass<T> //继承必须明确类型
{
public:
T y;
newclass(T t1, T t2) :myclass(t1), y(t2) //调用父类的构造函数
{
}
void print()
{
std::cout << x << " " << y << std::endl;
}
};
void main()
{
myclass<int> *p = new newclass<int>(10,9);
p->print();
std::cin.get();
//运行结果是:10 9
}
当写成下面的函数时
void main()
{
newclass<std::string> my1("abc", "xyz");
my1.print();
std::cin.get();
//运行结果是:abc xyz
}
9.类模板继承普通类,普通类继承类模板等情况
#include<iostream>
#include <string>
//模板类之间的继承
//类模板可以直接继承类模板,类型必须传递
//普通类继承类模板,需要明确类型实例化类模板
//类模板继承普通类,常规的操作方式
//类模板当作普通哦类,需要模板参数对类进行实例化
template<class T> //抽象模板类
class myclass
{
public:
T x;
myclass(T t) :x(t)
{
}
virtual void print() = 0; //可以带有纯虚函数
};
template<class T>
class newclass :public myclass<T> //继承必须明确类型
{
public:
T y;
newclass(T t1, T t2) :myclass(t1), y(t2) //调用父类的构造函数
{
}
void print()
{
std::cout << x << " " << y << std::endl;
}
};
//普通类
class xyz
{
public:
int x;
int y;
int z;
xyz(int a, int b, int c) :x(a), y(b), z(c)
{
}
void print()
{
std::cout << x << y << z;
}
};
template<class T>
class newxyz :public xyz
{
public:
T a;
//构造的时候给父类初始化
newxyz(T t1, int a1, int b1, int c1) :xyz(a1, b1, c1), a(t1)
{
}
void print()
{
std::cout << "Ta=" << a << std::endl;
std::cout << x << y << z << std::endl;
}
};
/*普通类继承模板类的时候这是要确定类型*/
class classrun :public newxyz<int>
{
public:
int d = 1000;
//下面的构造函数要确定类型
classrun(int a2, int b2, int c2, int d2) :newxyz<int>(a2, b2, c2, d2)
{
}
void print()
{
std::cout << d << x << y << z << a;
}
};
void main1()
{
classrun run1(1, 2, 3, 4);
run1.print();
std::cin.get();
//运行结果是:10002341
}
void main()
{
std::string str1 = "china";
newxyz<std::string> new1(str1, 10, 90, 89);
new1.print();
std::cin.get();
//运行结果是:
//Ta=china
//109089
}
10.类模板与友元函数,类模板与友元类
#include <iostream>
#include <string>
#include <vector>
template<class T> class myclass;
template<class T> void print(myclass<T> & my, T t1);
template<class T>
class myclass
{
public:
//friend void print(myclass<T> & my,T t1);
//友元函数放在模板类的内部,实现重载
friend void print(myclass<T> & my, T t1);
friend myclass * operator+(const myclass<T> & my1, const myclass<T> & my2)
{
//下面的情况在栈上,用完了马山释放
//myclass class1
//堆上申请一个
myclass * p = new myclass(my1.x + my2.x, my1.y + my2.y);
return p;
}
myclass(T t1, T t2) :x(t1), y(t2)
{
}
//访问私有需要友元
private:
T x;
T y;
};
template<class T>
void print(myclass<T> & my, T t1)
{
std::cout << typeid(t1).name() << std::endl;
std::cout << my.x << " " << my.y << std::endl;
}
using namespace std;
void main()
{
myclass<int> my1(19, 29);
vector<int> v1;
vector<vector<int>> v2;
vector<vector<vector<int>>> v3;
//通过下面的方式对类型进行简写
using VEC = vector<vector<vector<int>>>; //C++11简写
VEC v4;//等价于三维int类型数据,模板
std::cin.get();
}
案例2
#include<iostream>
using namespace std;
//这里要声明模板类和友元函数
template<class T> class Object;
template<class T> void fun(const Object<T> &);
template<class T>
class Object
{
private:
T _d;
public:
Object(T d) :_d(d){}
//声明友元函数
friend void fun<T>(const Object<T> &);
};
template<class T>
void fun(const Object<T> & obj)
{
cout << obj._d << endl;
}
int main()
{
Object<double> obj(111.4);
fun<double>(obj);
std::cin.get();
return 0;
//运行结果:111.4
}
类模板与友元类
#include <iostream>
using namespace std;
//定义友元类和友元函数
template<class T> class myclass;
template<class T> void print(const myclass<T> &);
template<class T> class runclass;
template<class T>
class myclass
{
private:
T x;
T y;
public:
myclass(T t1, T t2) :x(t1), y(t2)
{
}
//友元必须类名
friend void print<T>(const myclass<T> &);
friend class runclass<T>;
};
template<class T>
void print(const myclass<T> &my)
{
std::cout << my.x << " " << my.y << std::endl;
}
template<class T>
class runclass
{
public:
void print(const myclass<T> & my)
{
std::cout << my.x << " " << my.y << std::endl;
}
};
void main()
{
myclass<int> my1(19, 29);
myclass<int> my2(11,1);
print(my2);
runclass<int> runclass1;
runclass1.print(my1);
std::cin.get();
//运行结果:
//11 1
//19 29
}
11.类模板当作模板参数
#include<iostream>
#include <string>
using namespace std;
//类模板当作一个类的参数
//设计STL的时候用到
template<class T>
class ren //一个通用的类的类模板
{
public:
T name;
ren(T t) :name(t)
{
}
};
//使用类模板当作模板参数的类
template<template<class T> class T1>
class people
{
public:
T1<string> t1x = "123123";//T1必须实例化 。必须结合
T1<string> num = "ABC"; //等价于ren类型
//T1 x
people(T1<string> &t1)
{
std::cout << typeid(t1).name() << std::endl;
std::cout << typeid(T1).name() << std::endl;
std::cout << t1.name << std::endl;
t1x = t1;
num = t1;
}
};
void main()
{
ren<string> ren1("hello8848");//基本数据类型
people<ren> people1(ren1); //嵌套的类模板
std::cout << people1.t1x.name << std::endl;
std::cout << people1.num.name << std::endl;
std::cout << ren1.name << std::endl;
std::cin.get();
}
运行结果:
12.类包装器
#include <iostream>
//类包装器,实现一个操作接口,操作多个类的方法
template<typename T,typename F>
T run(T t, F f)
{
return f(t);
}
int add(int num)
{
return num + 10;
}
class myclass
{
public:
int num;
myclass(int data) :num(data)
{
}
int operator ()(int X)
{
return X*num;
}
};
class myclassA
{
public:
int num;
myclassA(int data) :num(data)
{
}
int operator ()(int X)
{
std::cout << "A\n";
return X - num;
}
};
void main1()
{
myclass my1(5);
//函数作为参数
std::cout << run(101, my1) << std::endl;
//函数作为参数,下面的重载调用了()操作符
std::cout << run(101, myclassA(51)) << std::endl;
std::cin.get();
//运行结果是:
//505
//A
//50
}
void main()
{
auto num = 100;
auto func = add;
//调用add函数
std::cout << run(num, add) << std::endl;
std::cin.get();
//运行结果:110
}
13.类嵌套
#include<iostream>
//类的嵌套
class myclass
{
public:
class newclass
{
public:
int num;
} new1;
};
class newnewclass :public myclass
{
};
void main1()
{
newnewclass newx;
newx.myclass::new1.num = 10;
std::cout << newx.new1.num;
std::cin.get();
//运行结果:10
}
void main()
{
myclass myclass1;
myclass1.new1.num = 19;
std::cout << myclass1.new1.num;
std::cin.get();
//运行结果:19
}
14.类模板嵌套
#include <iostream>
template<class T>
class myclass
{
public:
class newclass
{
public:
int num;
} new1; //定义的方式
newclass new2;
template<class V>
class runclass
{
public:
V v1;
};//类模板后面不可以直接初始哈
runclass<T> t1;
runclass<double> t2;
};
void main()
{
myclass<int> my1;
my1.new1.num = 10;
//给嵌套类中的变量赋值
my1.t1.v1 = 12;
//给嵌套类中的变量赋值
my1.t2.v1 = 12.9;
std::cout << my1.t1.v1 << "\n" << my1.t2.v1;
std::cin.get();
//运行结果:
//12
//12.9
}
类模板,多种类型的类模板,自定义类模板,类模板的默认类型,数组的模板实现,友元和类模板,友元函数,类模板与静态变量,类模板与普通类之间互相继承,类模板作为模板参数,类嵌套,类模板嵌套,类包装器相关推荐
- 类型转换,类与类之间的转换,继承关系,继承与静态变量,子类父类重名,多继承,虚基类
常量的基本类型转换,例如:int num(10.8),这种方式是隐式转换. 通过函数的构造函数实现转换. 类类转换函数,当构造函数不能将类型转换成基本类型时.所以就有了类类转换函数,通过这种方式 ...
- Java 枚举类型原理分析为什么枚举比用静态变量多消耗两倍的内存
一 起源:枚举是一种特殊的数据类型,一般用来列举有限个.同类型的常量.它能保证参数的安全性,如方法声明传入的参数,必须是指定枚举中的常量.但是Android开发文档指出,使用枚举会比使用静态变量多消耗 ...
- java 静态变量和非静态_Java中静态和非静态变量之间的区别
变量为我们提供了程序可以操纵的命名存储.Java中的每个变量都有一个特定的类型,该类型确定变量的内存大小和布局.可以存储在该内存中的值的范围:以及可以应用于该变量的一组操作. 静态变量 静态变量也称为 ...
- php定义常量和静态常量的区别,php静态变量与自定义常量的区别实例详解
php 静态变量与自定义常量的使用方法 ⚑ 静态变量的声明与使用 ⚑ 自定义常量的使用方式 什么是静态变量? 静态变量是指用static声明的变量,这种变量与局部变量的区别是,当静态变量离开了它的作用 ...
- 笔记②:牛客校招冲刺集训营---C++工程师(面向对象(友元、运算符重载、继承、多态) -- 内存管理 -- 名称空间、模板(类模板/函数模板) -- STL)
0618 C++工程师 第5章 高频考点与真题精讲 5.1 指针 & 5.2 函数 5.3 面向对象(和5.4.5.5共三次直播课) 5.3.1 - 5.3.11 5.3.12-14 友元 友 ...
- c++模板类静态成员变量_一文讲透父子类中静态变量,成员变量初始化顺序原理...
推荐: 从面试到入职到离职,我在B站工作的30天时光 爱了爱了,Alibaba顶级MySQL调优手册到手,加薪妥了 爱了爱了,Spring Cloud Alibaba内部微服务架构笔记真的太牛了 本文 ...
- Long类型传到前端失去精度(2):Long类型不是实体类的某一个字段,Long类型是一个函数的返回值
Long类型传到前端失去精度(2):Long类型不是实体类的某一个字段,Long类型是一个函数的返回值 又是转换Mybatis-Plus的一天,又遇到了之前熟悉的问题:Long类型传到前端失去精度.可 ...
- Hibernate中的Entity类之间的继承关系之一MappedSuperclass
在hibernate中,Entity类可以继承Entity类或非Entity类.但是,关系数据库表之间不存在继承的关系.那么在Entity类之间的继承关系,在数据库表中如何表示呢? Hibernate ...
- 某IT公司有多名员工,按员工负责的工作不同,进行了部门的划分(研发部员工、维护部员工)。完成员工体系中所有类的定义,并指定类之间的继承关系。进行xx工程师类的对象创建,完成工作方法的调用。
某IT公司有多名员工,按员工负责的工作不同,进行了部门的划分(研发部员工.维护部员工).研发部根据所需研发的内容不同,又分为JavaEE工程师.Android工程师:维护部根据所需维护的内容不同,又分 ...
最新文章
- QIIME 2用户文档. 8数据导入Importing data(2018.11)
- Elasticsearch 常用配置参数总结
- 解决 Python shell 中 Delete/Backspace 键乱码问题
- 光栅衍射主极大个数_大学物理——光的干涉和衍射(二)
- 聊聊flink Table的OrderBy及Limit
- 突发!哈佛要求本科生5天内搬走,国际学生恐无家可归
- 区块链网络安全平台Hapi Protocol将在Poolz上进行 IDO
- 用于android天气开发的背景图,Android开发天气预报APP的设计与实现毕业设计.pdf
- TensorFlow相关教程:使用tf.data加载图片
- 矩阵的秩(Rank)
- 希尔伯特变换到底有什么用
- 需求分析师面试题案例_如何准备作为分析师的业务案例面试
- 高压带电显示器局放检测面板式四合一局放在线监测/带电故障显示/无线测温装置
- latext配置 vscode_VSCode配置LaTeX编辑器
- 离职 需要注意三个问题
- RDF和SPARQL
- 为什么图像成像时近大远小?
- en-win7-x64-sp1 + vs2015.3 + Lenovo Z470 装机镜像
- 自学软件测试,该读些什么书籍?
- 建筑CAD软件导出超大T3或T8格式图纸时卡顿怎么办?
热门文章
- Spring IoC(二)IoC容器的初始化过程
- VTK:定向包围圆柱体用法实战
- wxWidgets 的打印演示
- wxWidgets:wxTaskBarIcon类用法
- boost::uuid::nil_generator相关的测试程序
- boost::rotate相关的测试程序
- BOOST_PROTO_EXTENDS_MEMBERS宏相关的测试程序
- boost::mp11::mp_less相关用法的测试程序
- boost::detail::conversion::try_lexical_convert用法的测试程序
- ITK:计算图像谱密度