类模板,多种类型的类模板,自定义类模板,类模板的默认类型,数组的模板实现,友元和类模板,友元函数,类模板与静态变量,类模板与普通类之间互相继承,类模板作为模板参数,类嵌套,类模板嵌套,类包装器



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;
}
  1. 多种类型的类模板
案例:

#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

}

时间: 2024-12-05 13:11:04

类模板,多种类型的类模板,自定义类模板,类模板的默认类型,数组的模板实现,友元和类模板,友元函数,类模板与静态变量,类模板与普通类之间互相继承,类模板作为模板参数,类嵌套,类模板嵌套,类包装器的相关文章

类型转换,类与类之间的转换,继承关系,继承与静态变量,子类父类重名,多继承,虚基类

 常量的基本类型转换,例如:int num(10.8),这种方式是隐式转换. 通过函数的构造函数实现转换. 类类转换函数,当构造函数不能将类型转换成基本类型时.所以就有了类类转换函数,通过这种方式. 案例: #include <iostream> class fushu { public: //通过加explicit的这种方式避免隐式转换,避免引发歧义 explicit fushu(int num) { x = num; y = num; } void print() { std::cou

一个类成员函数的局部静态变量问题

之前工作中遇到一个问题,就像题目中描述的那样,看起来题目有些拗口复杂,这里解释下,当时遇到的需求需要这样处理:调用某个类对象的某个成员函数时,第一次有具体意义的,其他时候都是保持不变的.无意义的.这个需求可以看做是在调用某成员函数时,第一次进行初始化,其他时候不进行操作,即在首次调用时进行初始化,根据这点,很容易想到c/c++里面的static变量,它的作用是保持变量内容的持久,存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化.根据需求,使用static局部变量,写下

谈谈java中静态变量与静态方法继承的问题

谈谈java中静态变量与静态方法继承的问题 学习的中如果遇到不明白或者不清楚的的时候,就是自己做些测试,自己去试试,这次我就做一个关于静态变量的继承和静态方法继承问题的测试. 首先我先建一个父类: 这样我在建一个子类: 这些都准备好以后,我对子类创建对象,然后用  类名.静态变量/静态方法  和  对象名.静态方法/静态变量  对他们输出的结果进行测试. 这样输出种类有: 这样我输出的结果是: 这样来总结一下: 1. 通过类名来调用子类中的静态变量和静态方法,当父类与子类相同时是,子类会隐藏父类

【C/C++学院】0825-类模板/final_override/类模板与普通类的派生类模板虚函数抽象模板类/类模板友元/位运算算法以及类声明/Rtti 实时类型检测/高级new创建/类以及函数包装器

类模板 类模板多个类型默认类型简单数组模板 #pragma once template <class T=int>//类模板可以有一个默认的值 class myArray { public: myArray(); ~myArray(); }; #include "myArray.h" template <class T=int>//每一个函数都需要加上一个默认的值 myArray<T>::myArray() //类模板成员函数在外部,需要加载类型初始

验证当多个类之间有继承关系时,创建子类对象会导致父类初始化块的执行。

结果:当多个类之间有继承关系时,创建子类对象会导致父类初始化块的执行.

Hibernate中的Entity类之间的继承关系之一MappedSuperclass

在hibernate中,Entity类可以继承Entity类或非Entity类.但是,关系数据库表之间不存在继承的关系.那么在Entity类之间的继承关系,在数据库表中如何表示呢? Hibernate提供了4种兼容JPA的策略,解决Entity类的继承与关系数据库表的对应不匹配问题.这里介绍第一种MappedSuperclass. 在这种策略中,存在如下特征: 只在Entity类之间存在继承关系,其中的父Entity类使用@javax.persistence.MappedSuperclass标注

在Java中String类为什么要设计成final?String真的不可变吗?其他基本类型的包装类也是不可变的吗?

最近突然被问到String为什么被设计为不可变,当时有点懵,这个问题一直像bug一样存在,竟然没有发现,没有思考到,在此总结一下. 1.String的不可变String类被final修饰,是不可继承和修改的.当一个String变量被第二次赋值时,不是在原有内存地址上修改数据,而是在内存中重新开辟一块内存地址,并指向新地址. String类为什么要被设计为是final的? 1.不可变性支持线程安全. 2.不可变性支持字符串常量池,提升性能. 3.String字符串作为最常用数据类型之一,不可变防止

自定义类签发校验token-实现多方式登录-自定义反爬类-admin后台表管理字段自定义-群查接口-搜索-排序-分页

目录 复习 今日 签发token 校验token 案例:实现多方式登陆签发token 案例:自定义认证反爬规则的认证类 admin使用自定义User表:新增用户密码密文 群查接口各种筛选组件数据准备 drf搜索过滤组件 drf排序过滤组件 drf基础分页组件 复习 """ 频率组件:限制接口的访问频率 源码分析:初始化方法.判断是否有权限方法.计数等待时间方法 自定义频率组件: class MyThrottle(SimpleRateThrottle): scope = 'sm

类的相关知识(封装、继承、多态、方法、构造方法、接口、抽象类、静态方法、静态变量等)

类 通过抽象,得到的某一个事物的共同特征. 1.类是抽象的,概念的,代表一类事物,比如人类,猫类-- 2.对象是具体的,实际的,代表一个具体事物 3.类是对象的模板,对象是类的一个个体,实例 class Cat           // Java中类名的首字母大写 { //下面的就是类的成员变量.属性 Int age; String name; String color; } 类的结构: Package 包名: Class 类名 extends 父类 implements 接口名 { 成员变量(