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

简介:  1.第一个最简单的类模板案例 #include "mainwindow.h" #include <QApplication> #include <QPushButton> #include <QLabel>   template<class T>    class run {

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

}

目录
相关文章
|
9月前
|
存储 算法 安全
04-📝C++核心语法|面向对象2【友元、内部类与局部类、强化训练(数组类封装)、运算符重载、仿函数、模板、类型转换、 C++标准、错误&&异常、智能指针】
复习`C++核心语法`,且适当进行汇编探索底层实现原理,进一步夯实基础,为以后的`底层开发`、`音视频开发`、`跨平台开发`、`算法`等方向的进一步学习埋下伏笔。
04-📝C++核心语法|面向对象2【友元、内部类与局部类、强化训练(数组类封装)、运算符重载、仿函数、模板、类型转换、 C++标准、错误&&异常、智能指针】
|
4月前
类模板和继承
类模板和继承
18 0
|
6月前
|
存储 编译器 C++
【C++】C++11右值引用|新增默认成员函数|可变参数模版|lambda表达式(上)
【C++】C++11右值引用|新增默认成员函数|可变参数模版|lambda表达式(上)
|
6月前
|
算法 编译器 C语言
【C++】C++11右值引用|新增默认成员函数|可变参数模版|lambda表达式(下)
【C++】C++11右值引用|新增默认成员函数|可变参数模版|lambda表达式(下)
|
6月前
|
编译器 C++
【C++】C++11右值引用|新增默认成员函数|可变参数模版|lambda表达式(中)
【C++】C++11右值引用|新增默认成员函数|可变参数模版|lambda表达式(中)
|
11月前
|
编译器 C++
C++模板(函数模板,类模板)的基本使用与非类型模板参数与模板的特化(1)
我们先来思考一个问题,如果有人让你实现一个通用的交换函数你们会怎么做?有的小伙伴会说,我会使用函数重载的方式,把每一种类型重载,但…难道就没有更容易的办法,不用敲那么多次吗?ok,就来看看我们今天要介绍的模板,能很好的帮你解决这个问题。
121 0
|
11月前
|
编译器 C++
C++模板(函数模板,类模板)的基本使用与非类型模板参数与模板的特化(2)
C++模板(函数模板,类模板)的基本使用与非类型模板参数与模板的特化
104 0
|
编译器 C语言 C++
【C++要笑着学】泛型编程 | 函数模板 | 函数模板实例化 | 类模板(一)
本章将正式开始介绍C++中的模板,为了能让大家更好地体会到用模板多是件美事!我们将会举例说明,大家可以试着把自己带入到文章中,跟着思路去阅读和思考,真的会很有意思!如果你对网络流行梗有了解,读起来将会更有意思!
97 0
【C++要笑着学】泛型编程 | 函数模板 | 函数模板实例化 | 类模板(一)
|
存储 编译器 C++
【C++要笑着学】泛型编程 | 函数模板 | 函数模板实例化 | 类模板(二)
本章将正式开始介绍C++中的模板,为了能让大家更好地体会到用模板多是件美事!我们将会举例说明,大家可以试着把自己带入到文章中,跟着思路去阅读和思考,真的会很有意思!如果你对网络流行梗有了解,读起来将会更有意思!
103 1
【C++要笑着学】泛型编程 | 函数模板 | 函数模板实例化 | 类模板(二)