• C++学习笔记之 模板


    模板

    概念

    模板是泛型编程的基础,泛型编程即以一种独立于任何特定类型的方式编写代码,即不具体制定数据类型

    模板是创建泛型类或函数的蓝图或公式

    函数模板

    基本语法

    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    
    // 函数模板实现通用数据类型交换
    template<typename T> // T属于通用数据类型
    void mySwap(T &a,T &b) { // 模板可以将类型参数化
        T temp = a;
        a = b;
        b = temp;
    }
    
    // 使用函数模板
    void test01() {
        // 1. 自动类型推导
        int a = 0,b = 1;
        cout << "a = " << a << ",b = " << b << endl;
        mySwap(a,b);
        cout << "a = " << a << ",b = " << b << endl;
        
        // 2. 显式指定类型
        mySwap<int>(a,b);
        cout << "a = " << a << ",b = " << b << endl;
        mySwap(a,b);
        cout << "a = " << a << ",b = " << b << endl;
        
        // 注意:模板必须推导出T的类型才能使用,否则不能单独使用
    }
    
    int main() {
        test01();
    
        return EXIT_SUCCESS;
    }
    
    a = 0,b = 1
    a = 1,b = 0
    a = 0,b = 1
    a = 1,b = 0
    

    函数模板与普通函数区别

    1. 普通函数可以发生隐式类型转化
    2. 如果普通函数和函数模板(同名)都可以匹配,优先匹配普通函数
    3. 如果要强制调用函数模板,则要加空模板参数列表mySwap<>(a,b)
    4. 函数模板也可以产生函数重载
    5. 如果函数模板可以产生更好的匹配,那么优先匹配函数模板

    函数模板的局限和解决

    #include <iostream>
    
    using namespace std;
    
    class Person
    {
    public:
        int m_Age;
        Person(int age) : m_Age(age) {
            ;
        }
    };
    
    // 模板并不真正通用
    // 对于特殊数据类型,可以具体化实现
    template<class T>
    bool myCompare(T &a, T &b) {
        return a == b;
    }
    
    // 利用具体化实现,解决特殊数据类型
    // 语法:template<> 函数名 + 具体实现
    template<> bool myCompare(Person &a, Person &b) {
        return a.m_Age == b.m_Age;
    }
    
    int main() {
        Person p1 = Person(18);
        Person p2 = Person(20);
        cout << myCompare(p1,p2) << endl;
    
        return EXIT_SUCCESS;
    }
    
    0
    

    类模板

    基本语法

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    // 模板中也可以指定默认参数
    template<class T1,class T2 = int>
    class Person
    {
    public:
        T1 m_Name;
        T2 m_Age;
        
        Person(T1 name, T2 age) {
            this->m_Age = age;
            this->m_Name = name;
        }
    };
    
    int main() {
        // Person p(18,"Tom"); 类模板使用时,不可以自动类型推导,必须显式指定
        Person <string,int>p("Tom",18);
    
        return EXIT_SUCCESS;
    }
    

    类模板中成员函数创建时机

    #include<iostream>
    
    using namespace std;
    
    class Person1
    {
    public:
        void showPerson1()
        {
            cout << "showPerson1" << endl;
        }
    };
    
    class Person2
    {
    public:
        void showPerson2()
        {
            cout << "showPerson2" << endl;
        }
    };
    
    
    //类模板中成员函数并不是一开始创建,而是在替换T后,才去生成
    
    template<class T>
    class testClass
    {
    public:
        void func1()
        {
            obj.showPerson1();
        }
    
        void func2()
        {
            obj.showPerson2();
        }
    
        T obj;
    };
    
    
    void test01()
    {
        testClass<Person2>tc;
        //tc.func1();
        tc.func2();
    
    }
    
    
    int main(){
    
        test01();
    
        return EXIT_SUCCESS;
    }
    

    类模板做函数参数

    #include<iostream>
    using namespace std;
    #include <string>
    
    //模板中 也可以使用默认参数
    template<class T1, class T2>
    class Person
    {
    public:
    
    	Person(T1 name, T2 age)
    	{
    		this->m_Name = name;
    		this->m_Age = age;
    	}
    
    	void showPerson()
    	{
    		cout << "姓名: " << this->m_Name << " 年龄: " << this->m_Age << endl;
    	}
    
    	T1 m_Name;
    	T2 m_Age;
    };
    
    //1、指定传入类型
    void doWork(Person <string, int>&p)
    {
    	p.showPerson();
    }
    
    void test01()
    {
    	Person <string,int>p1("Tom", 100);
    	doWork(p1);
    }
    
    //2、将参数模板化
    template<class T1,class T2>
    void doWork2(Person <T1, T2>&p)
    {
    	cout << "T1 = " << typeid(T1).name() << endl;
    	cout << "T2 = " << typeid(T2).name() << endl;
    	p.showPerson();
    }
    
    void test02()
    {
    	Person <string, int>p1("Jerry", 100);
    	doWork2(p1);
    }
    
    
    //3、将类模板化
    template<class T>
    void doWork3(T &p)
    {
    	cout << "T = " << typeid(T).name() << endl;
    	p.showPerson();
    }
    
    void test03()
    {
    	Person <string, int>p1("Bill", 100);
    	doWork3(p1);
    }
    
    
    
    int main(){
    
    	//test01();
    	//test02();
    	test03();
    
    	system("pause");
    	return EXIT_SUCCESS;
    }
    
    T = 6PersonINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEiE
    姓名: Bill 年龄: 100
    

    类模板遇到继承时的问题和解决

    #include<iostream>
    using namespace std;
    
    template<class T>
    class Base
    {
    public:
    	T m_A;
    };
    
    //子类在继承时,必须确定出父类的T的数据类型,否则无法给T分配内存空间
    class Son :public Base<int>
    {
    
    };
    
    
    template<class T>
    class Base2
    {
    public:
    	T m_A;
    };
    
    template<class T1, class T2>
    class Son2 :public Base2<T2>
    {
    public:
    	Son2()
    	{
    		cout << "T1的类型为: " << typeid(T1).name() << endl;
    		cout << "T2的类型为: " << typeid(T2).name() << endl;
    	}
    
    	T1 m_B;
    };
    
    
    void test01()
    {
    	Son2<int, double> s;
    }
    
    int main(){
    
    	test01();
    
    	system("pause");
    	return EXIT_SUCCESS;
    }
    
    T1的类型为: i
    T2的类型为: d
    

    类模板成员函数类外实现

    #include<iostream>
    using namespace std;
    #include <string>
    
    
    template<class T1, class T2>
    class Person
    {
    public:
    
        Person(T1 name, T2 age);
        //{
        //	this->m_Name = name;
        //	this->m_Age = age;
        //}
    
        void showPerson();
        //{
        //	cout << "姓名: " << this->m_Name << " 年龄: " << this->m_Age << endl;
        //}
    
        T1 m_Name;
        T2 m_Age;
    };
    
    template<class T1,class T2>
    Person<T1,T2>::Person(T1 name, T2 age)
    {
        this->m_Name = name;
        this->m_Age = age;
    }
    
    template<class T1, class T2>
    void Person<T1,T2>::showPerson()
    {
        cout << "姓名: " << this->m_Name << " 年龄: " << this->m_Age << endl;
    }
    
    
    void test01()
    {
        Person<string, int>p("aaa", 10);
        p.showPerson();
    }
    
    int main(){
        test01();
        return EXIT_SUCCESS;
    }
    
    姓名: aaa 年龄: 10
    

    类模板和友元

    类内实现

    #include<iostream>
    using namespace std;
    #include <string>
    
    template<class T1,class T2>
    class Person
    {
    
    	friend void printPerson(Person<T1, T2>& p)
    	{
    		cout << "姓名: " << p.m_Name << " 年龄: " << p.m_Age << endl;
    	}
    
    public:
    
    	Person(T1 name, T2 age)
    	{
    		this->m_Name = name;
    		this->m_Age = age;
    	}
    
    private:
    	T1 m_Name;
    	T2 m_Age;
    };
    
    
    void test01()
    {
    	Person<string, int>p("Tom", 111);
    
    	printPerson(p);
    }
    
    int main(){
    
    	test01();
    
    	return EXIT_SUCCESS;
    }
    

    类外实现

    #include<iostream>
    using namespace std;
    #include <string>
    
    //先让编译器看到Person类声明
    template<class T1, class T2>class Person;
    
    //先让编译器看到函数模板 printPerson的存在
    template<class T1, class T2> void printPerson(Person<T1, T2>& p);
    
    
    template<class T1, class T2>
    void printPerson2(Person<T1, T2>& p)
    {
    	cout << "姓名: " << p.m_Name << " 年龄: " << p.m_Age << endl;
    }
    
    template<class T1, class T2>
    class Person
    {
    
    	friend void printPerson<>(Person<T1, T2>& p);
    
    	friend void printPerson2<>(Person<T1, T2>& p);
    
    public:
    
    	Person(T1 name, T2 age)
    	{
    		this->m_Name = name;
    		this->m_Age = age;
    	}
    
    private:
    	T1 m_Name;
    	T2 m_Age;
    };
    
    template<class T1,class T2>
    void printPerson(Person<T1, T2>& p)
    {
    	cout << "姓名: " << p.m_Name << " 年龄: " << p.m_Age << endl;
    }
    
    
    void test01()
    {
    	Person<string, int>p("Tom", 222);
    
    	printPerson(p);
    	printPerson2(p);
    }
    
    int main(){
    
    	test01();
    
    	return EXIT_SUCCESS;
    }
    
  • 相关阅读:
    C# Workbook读取Execl数据
    C# Task
    Json/XML序列化和反序列化
    C# RSA加解密和MD5加密
    SqlServer基本操作
    SQL Server基础优化
    Http请求基本方法
    ASP.NET MVC基础知识
    简单的五险一金计算器
    PHP基础入门(三)
  • 原文地址:https://www.cnblogs.com/zhujiangyu/p/14091394.html
Copyright © 2020-2023  润新知