c++day6

一.类模板

(1)概念

类模板中定义的函数参数或者属性等数据类型可以参数化

template <typename T,typename U,...>

class 类型

{};

#include <iostream>
using namespace std;
template <typename T,typename U>
class Test
{
    private:
        T a;
        U b;
    public:
        Test(T a,U b)
        {
            this->a = a;
            this->b = b;
        }
        void show()
        {
            cout << a << " " << b << endl;
        }
};
int main(int argc, const char *argv[])
{
    Test<int,char> t1(1,'a');
    t1.show();
    return 0;
}
ps:类模板调用一定要显式调用

(2)模板类的继承

#include <iostream>
using namespace std;
template <typename T>
class Parent
{
    protected:
        T a;
    public:
        Parent(T a)
        {
            this->a = a;
        }
        void show()
        {
            cout << a << endl;
        }
};
class Child:public Parent<int>
{
    public:
        Child(int a):Parent(a)
        {}
        void show()
        {
            cout << a << endl;
        }
};
template <typename T,typename U>
class Child2:public Parent<T>
{
    private:
        U b;
    public:
        Child2(T a,U b):Parent<T>(a)
        {
            this->b = b;
        }
        void show()
        {
            cout << this->a << " " << this->b << endl;
        }
};
int main(int argc, const char *argv[])
{
    Child c1(1);
    c1.show();
    Child2<int,double> c2(1,1.11);
    c2.show();
    return 0;
}
ps:模板类派生普通类,继承的同时对基类实例化

模板类派生模板类,继承的同时不需要对基类实例化

(3)模板类的声明

#include <iostream>
using namespace std;
template <typename T>
class Test
{
    public:
        Test(T a);
        void show();
        ~Test();
    private:
        T a;
};

template <typename T>
Test<T>::Test(T a)
{
    this->a = a;
}

template <typename T>
void Test<T>::show()
{
    cout << a << endl;
}

template <typename T>
Test<T>::~Test()
{

}
int main(int argc, const char *argv[])
{
    Test<int> t1(1);
    t1.show();
    return 0;
}

(4)模板类中的static

#include <iostream>
using namespace std;
template <typename T>
class Test
{
    public:
        Test(T a);
        void show();
        ~Test();
    private:
        T a;
    public:
        static int count;
};
template <typename T>
int Test<T>::count = 0;

template <typename T>
Test<T>::Test(T a)
{
    this->a = a;
    count++;
}

template <typename T>
void Test<T>::show()
{
    cout << a << endl;
}
template <typename T>
Test<T>::~Test()
{

}
int main(int argc, const char *argv[])
{
    Test<int> t1(1);
    Test<int> t2(1);
    Test<int> t3(1);
    Test<int> t4(1);
    Test<int> t5(1);

    Test<char> t6('a');
    Test<char> t7('a');
    Test<char> t8('a');
    cout << Test<int>::count << endl;
    cout << Test<char>::count << endl;
    return 0;
}
二.成员模板

2.1为什么要使用成员模板

#include <iostream>
using namespace std;
template <typename T>
class Test
{
    public:
        T m_a;
    public:
        void print(const Test<T> &a)
        {
            cout << a.m_a << endl;
        }
};
int main(int argc, const char *argv[])
{
    Test<int> a;
    a.m_a = 1;
    Test<double> b;
    b.m_a = 1.123;
    a.print(a);
    a.print(b);
    return 0;
}

报错无法运行

2.2成员模板的实现

#include <iostream>
using namespace std;
template <typename T>
class Test
{
    public:
        T m_a;
    public:
        template <typename X>
        void print(const Test<X> &a)
        {
            cout << a.m_a << endl;
        }
};
int main(int argc, const char *argv[])
{
    Test<int> a;
    a.m_a = 1;
    Test<double> b;
    b.m_a = 1.123;
    a.print(a);
    a.print(b);
    return 0;
}
 三.关键词-typename

3.1内嵌依赖类型名

内嵌:是指在类的内部定义的

依赖:依赖于某一个模板参数

类型名:最终要指出的这个类型名

3.2实例

#include <iostream>
using namespace std;
template <typename T>
class Test
{
    public:
        T m_a;
        typedef T* PT;
    public:
        template <typename X>
        void print(const Test<X> &a)
        {
            cout << a.m_a << endl;
        }
};
int main(int argc, const char *argv[])
{
    int num = 100;
    Test<int>::PT p = &num;
    return 0;
}
四.using给模板起别名

#include <iostream>
using namespace std;
template <typename T,typename U>
class Test
{
    public:
        T m_a;
        typedef T* PT;
    public:
};
template <typename S>
using MyA = Test<string,S>;
using s32 = int;
using P_func = void(*)(int,int);
int main(int argc, const char *argv[])
{
    Test<string,int> a;
    MyA<int> a2;
    return 0;
}
五.实例化

5.1 #pragma once

1.ifndef方法是c/c++的标准支持,比较常用的方式

#pragma once 一般由编译器提供保证,功能是保证同一个文件不会被包含多次

visual studio 2017之后的版本新建的头文件都会自带#pragma once

2.兼容性:#pragma once产生于ifndef之后,ifndef不受任何编译器的限制,而#pragma once方法有些编译器不支持,兼容性不够好

3.ifndef可以针对文件中的一部分代码,而#pragma once只针对整个文件

4.ifndef更加灵活,兼容性好,#pragma once操作简单,效率更高

5.2隐式实例化

隐式实例化是指在函数调用的时候,如果没有发现与之相匹配的函数存在,编译器会寻找同名的函数模板,如果可以成功进行参数的推演,就对函数模板实例化

类模板同上。

5.3显示实例化

显式实例化:外部实例化,在不发生函数调用的时候将函数模板实例化

类模板同上

5.3.1函数模板的显式实例化

template[返回值类型][函数名]<实际类型列表>(函数参数列表)

template void func<int>(const int&);

5.3.2类模板的显式实例化

template class Test<int>;

作用:减少隐式实例化多个函数和类的开销,只实例化一次(不同编译器处理机制可能不同)

#pragma once
#include <iostream>
#include <string>
#include <vector>
using namespace std ;
template < typename T >
void print ( const T & t )
{
cout << t << endl ;
}
template < typename T , typename CONT = vector < T >>
class Stack
{
public :
Stack ()
{
top = - 1 ;
}
void push ( T num )
{
data . push_back ( num );
}
void pop ()
{
//return data.pop_back();
}
int top ;
CONT data ; //vector<T> data;
#include "template.h"
template void print < int > ( const int & t ); // 显示实例化,只实例化一次
template class Stack < int , vector < int >> ;
void Func ()
{
print ( 5 );
print ( "hello" );
print ( 10 );
Stack < int > s ;
Stack < string > s1 ;
}
#include "template.h"
extern void Func ();
template void print < int > ( const int & t ); // 显示实例化,只实例化一次
int main ( void )
{
print ( 5 );
print ( "hello" );
print ( 10 );
Stack < int > s ;
Stack < string > s1 ;
Func ();
}
5.4模板全特化和偏特化
5.4.1为什么要模板特化?
因为编译器认为,对于特定的类型,如果你能对某一个功能更好的实现,那么就该听你的,模板实例化时会优先匹配“模板参数”最符合的那个特化的版本
模板特化的前提要求是模板已经泛化
(1)类模板的全特化
#include <iostream>
#include <string>
using namespace std;
class A
{
    public:
        A()
        {}
        int m_a;
};
template <typename T,typename U>
class Test
{
    public:
        T m_a;
        U m_b;
    public:
        void print()
        {
            cout << m_a << endl;
            cout << m_b << endl;
        }
};
template <>
class Test<A,string>
{
    public:
        A m_a;
        string m_b;
    public:
        void print()
        {
            cout << "class Test<A,string>" << endl;
            cout << m_a.m_a << endl;
            cout << m_b << endl;
        }
};
int main(int argc, const char *argv[])
{
    Test<int,string> a;
    a.m_a = 1;
    a.m_b = "helloworld";
    a.print();
    A tb;
    Test<A,string> s1;
    s1.m_a = tb;
    s1.m_b = "world";
    s1.print();
    return 0;
}
(2)类模板的偏特化
#include <iostream>
#include <string>
using namespace std;
class A
{
    public:
        A()
        {}
        int m_a;
};
template <typename T,typename U>
class Test
{
    public:
        T m_a;
        U m_b;
    public:
        void print()
        {
            cout << m_a << endl;
            cout << m_b << endl;
        }
};
template <typename T>
class Test<T,string>
{
    public:
        T m_a;
        string m_b;
    public:
        void print()
        {
            cout << "class Test<T,string>" << endl;
            cout << m_a << endl;
            cout << "name:" << m_b << endl;
        }
};
int main(int argc, const char *argv[])
{
    Test<int,string> a;
    a.m_a = 1;
    a.m_b = "helloworld";
    a.print();
    return 0;
}
(3)类模板参数范围偏特化
int----->const int      T------>T*         T--------->T&
#include <iostream>
#include <string>
using namespace std;
class A
{
    public:
        A()
        {}
        int m_a;
};
template <typename T,typename U>
class Test
{
    public:    
        T m_a;
        U m_b;
    public:
        void print()
        {
            cout << m_a << endl;
            cout << m_b << endl;
        }
};
template <typename T,typename U>
class Test<const T,const U>
{
    public:
        T m_a;
        U m_b;
    public:
        void print()
        {
            cout << "class Test<const T,const U>" << endl;
        }
};
int main(int argc, const char *argv[])
{
    Test<const int,const int> a1;
    a1.print();
    return 0;
}
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值