模板零基础C++

模板

  • 函数模板

1-普通函数作模板

#include <iostream>
using namespace std;

template <class T>void fun(T m_a, T m_b)//实际上是一行
{
    cout << m_a << endl
         << m_b
         << endl;
}

int main()
{ //隐式调用
    fun("aa", "vvvv");
    fun(11, 33);
    fun(1.11111, 2.222222);
    //显式调用
    fun<string>("abab", "cdcd");
    fun<double>(0.11, 0.23232);
}

2-类的成员函数作模板


// 类的成员函数作模板
#include <iostream>
using namespace std;
class add
{
    int a;
    int b;

public:
    //类中声明且在类中实现
    template <class T>
    void print(T a, T b)
    {
        cout << a << "\t" << b << endl;
    }
    template <class T> //函数模板的返回值也可以模板化
    T Add(T a, T b)
    {
        return (a + b);
    }
    
    template <class int, class T2, class T3 = int> //函数模板可以缺省
    T3 multipy(int a, T2 b)
    {
        return a * b;
    }
//仅在类中声明,在类外实现。
    template <class Tint, class TT2 = int>
    TT2 m_return(Tint a); 
};
//类外实现
template <class Tint, class TT2 = int>//类外实现,必须加上template <class Tint, class TT2 = int>
TT2 add::m_return(Tint a)
{
    return a;
};

int main()
{
    add a1;
    a1.print(1, 3);
    cout << a1.Add(22, 33) << endl;
    cout << a1.multipy(1.3, 5) << endl;
    cout << a1.m_return(99.99) << endl;
}

//只需要知道类外实现成员函数的时候要加上template<未知类型>。

  • 模板类

// 模板类, 多文件编写代码时,类模板中函数声明和实现不能分离
#include <iostream>
#include <string.h>
using namespace std;

template <class T1, class T2>
class person
{
protected:
    T1 name;
    T2 age;

public:
    //类中声明
    person(T1, T2);
    T2 print();
};

//类外定义
template<class T1,class T2>
person<T1,T2>::person(T1 name,T2 age):name(name),age(age){};
//模板类不是实际的类,所有用到类名的地方都必须使用 类名<未知类型> 方法使用,除了构造函数那里不用,因为构造函数名只是根类名相同,但不是类名

template<class T1, class T2>
T2 person<T1 ,T2>::print()
//所有用到类名的地方都必须使用 类名<未知类型> 方法使用

{
    return (age+age/2);
}

int main()
{
person <string,int> p1("xiaobai",23);//模板类 必须显式定义对象,  所有用到类名的地方都必须使用 类名<未知类型> 方法使用
cout<<p1.print()<<endl;

}

模板类的派生

1-模板类派生出模板子类

#include <iostream>
#include <string.h>
using namespace std;

template <class T1, class T2>
class person
{
protected:
    T1 name;
    T2 age;

public:
    //类中声明
    person(T1 name, T2 age);
    T2 print();
};

template <class T1, class T2, class T3>//记得加上这个,T1和T2是父类的,T3是子类的
class boy : public person<T1, T2>
{
protected:
    T3 score;

public:
    boy(T1 name, T2 age, T3 score) : person<T1, T2>(name, age), score(score){}; //别忘了类名要加<未知类型>
    T3 print()
    {
        cout<<this->age<<"\t"<<this->name;

        return this->score;
    }
};

//类外定义
template <class T1, class T2>
person<T1, T2>::person(T1 name, T2 age) : name(name), age(age){};
//模板类不是实际的类,所有用到类名的地方都必须使用 类名<未知类型> 方法使用,除了构造函数那里不用,因为构造函数名只是根类名相同,但不是类名

template <class T1, class T2>
T2 person<T1, T2>::print()
//所有用到类名的地方都必须使用 类名<未知类型> 方法使用

{
    cout<<this->age<<"\t"<<this->name;
    return age*3 ;//
}

int main()
{
    person<string, int> p1("xiaobai", 23); //模板类 必须显式定义对象,  所有用到类名的地方都必须使用 类名<未知类型> 方法使用
    cout << p1.print() << endl;
    boy<string, int, string> PP1("xiao_mao", 33, "88.5");
    cout<<PP1.print()<<endl;
}

2-模板类派生出普通类

#include<iostream>
using namespace std;
/*欲得到模板类,就必须定义一个类模板,然后从才能从类模板按需求实例化出某个模板类*/
template<class T>
class A
{
	T v1;
public:
	void print()
	{
		cout << "v1=" << v1 << endl;
	}
};

/*普通类B 从 模板类A<int> 派生*/
class B :public A<int>//模板类A<int>
{
	int a;
public:
	B(int a_ = 0) :a(a_) { cout << "constructor was called !" << endl; }
	void set(int a_)
	{
		a = a_;
	}
	void print()
	{
		cout << "a=" << a << endl;
	}
};
int main()
{
	B obj(5);
	obj.print();
	obj.set(7);
	obj.print();
}

  • 模板自定义操作类型


//模板操作自定义类型:方法一采用重载函数,将<<重载为友元函数,能访问保护成员。也能打印对象
#include <iostream>
#include<string.h>
using namespace std;

class point
{
protected:
    int x;
    int y;
    string name;
//改正方法
friend ostream&operator<<(ostream &m_cout,const point &m_point)
{
m_cout<<m_point.x<<m_point.y<<m_point.name<<endl;
return m_cout;
};
public:
    point(int x, int y,string name):x(x),y(y),name(name){};
    

};
template< class T>
void print (T object)
{
    cout<<object<<endl;
}
int main()
{
    print(11);
    print("eee");
    //利用函数模板 打印基本数据类型不报错
    //如果打印自定义类型:比如直接打印对象时,需要重载函数
cout<<"******************************************************************"<<endl;
    point pp(11,22,"x and y");
    //隐式调用
    print (pp);
      //显式调用
      print<point> (pp);
    /*
    报错信息
    模板.cpp:122:9: error: no match for ‘operator<<’ (operand types are ‘std::ostream’ {aka ‘std::basic_ostream<char>’} and ‘point’)
  122 |     cout<<object<<endl;
    
    
    */



    }


方法二:采用类的特殊化(具体化,这部分将放到后面统一说明)


//模板操作自定义类型:方法一采用重载函数,将<<重载为友元函数,能访问保护成员。也能打印对象
#include <iostream>
#include<string.h>
using namespace std;
template<class T>
void print(T object)
{
    cout<<object<<endl;
    cout<<" choose_this "<<endl;
}
class point
{
   
    friend  void print<point>(point object);
protected:
    int x;
    int y;
    string name;
//改正方法

public:
    point(int x, int y,string name):x(x),y(y),name(name){};
    

};
template<>
void print<point>(point object)
{  
    cout<<object.x<<" "<<object.y<<" "<<object.name<<endl;
    cout<<" choose_that "<<endl;

}
int main()
{  print(255);
   cout<<"*****************************"<<endl;
    point pp(11,22,"x and y");
    //隐式调用
    print (pp);
}

程序结果

255
 choose_this 
*****************************
11 22 x and y
 choose_that 

模板的嵌套


//模板嵌套
#include<iostream>
#include<string.h>
using namespace std;

template <class T>
void print(T object)
{
    cout<<object<<endl;
};


template<class Ty1 ,class Ty2>
class person
{

friend ostream& operator<<(ostream &m_cout,const person&object)
{
    m_cout<<object.name<<" \t"<<object.age<<endl;
    return m_cout;
}

    protected:
    Ty1 name;
    Ty2 age;
    public:
    person(Ty1 name,Ty2 age);
    

};

template<class Ty1, class Ty2>
person<Ty1 ,Ty2>::person(Ty1 name ,Ty2 age) :name(name),age(age){};

int main()
{
    person<string,int>p1("aaaa",22);//类模板显示调用对象,
    
    
//显式
   print<person<string ,int>>(p1); 
//隐式
   print(p1);

}




程序结果

aaaa    22

aaaa    22

模板嵌套 二


//模板嵌套
#include<iostream>
#include<string.h>
using namespace std;



template<class Ty1 ,class Ty2>
class person
{

friend ostream& operator<<(ostream &m_cout,const person&object)
{
    m_cout<<object.data1<<" \t"<<object.data2<<endl;
    return m_cout;
}

    protected:
    Ty1 data1;
    Ty2 data2;
    public:
    person(Ty1 data1,Ty2 data2);
    

};

template<class Ty1, class Ty2>
person<Ty1 ,Ty2>::person(Ty1 data1 ,Ty2 data2) :data1(data1),data2(data2){};



template<class T1,class T2>
class DataShow{

protected:
T1 one;
T2 two;
public:

DataShow(T1 one ,T2 two):one(one),two(two){};
void print(){
    cout<<one<<"\t"<<two<<endl;
}
};



int main()
{

//类模板必须显式定义对象
person<string ,int> p1("xiao_mao",22);//用person 定义姓名 年龄

person<double ,double> p2(88.88,99.99);// 用person 定义两门分数

DataShow<person<string,int>,person<double,double>> student1(p1,p2);

student1.print();
    
//采用匿名对象的方法,不必给person起名
DataShow<person<string ,int>,person<double,double>> student2(person<string,int>("xiao_bai",23),person<double,double>(55.55,66.66));
student2.print();
    
    
 //可以使用using 语法简化代码
using ty =person<string ,int>;
using ty2=person<double,double>;

DataShow<ty,ty2> student3(ty("xiao_huang",24),ty2(66.66,55.66));
student3.print();


}



程序结果:

xiao_mao        22
        88.88   99.99

xiao_bai        23
        55.55   66.66

xiao_huang      24
        66.66   55.66

模板分文件编写

模板的特殊化(具体化)

特化和重载的区别

模板与友元函数

https://cloud.tencent.com/developer/article/1177313

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丁金金

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值