IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> c++基础知识点(5)特别详细 模板,隐式调用,显示调用,默认形参赋值,类模板,非类型实参等 -> 正文阅读

[C++知识库]c++基础知识点(5)特别详细 模板,隐式调用,显示调用,默认形参赋值,类模板,非类型实参等

首先让我们来看一段代码的实现

#include <iostream>
using namespace std;
int add(int x,int y)
{
    return x+y;
}
double add(double x,double y)
{
    return x+y;
}
int  add(char x,char y)
{
    return x+y;
}
int main()
{
    cout<<add(1,2)<<endl;
    cout<<add(3.1,2.3)<<endl;
    cout<<add('a','2')<<endl;
    return 0;
}

tips: int 和 char 可以隐式转换

我们如何只写一个函数就能实现下面三种不能类型数据的相加呢?

这里就要用到模板的知识,那我们来看模板。

一.模板

c++模板:是支持参数多态化的工具。

实质:设计一种通用类型的函数或类,在函数或类使用时,让数据成员,成员函数,函数返回值在实际使用时可以是任意类型。

目的:让程序员编写与类型无关的代码,是范型编程的基础。

函数模板:

? ? ? ? 针对函数参数类型不同的函数。

类模板:

? ? ? ? 针对数据成员,成员函数数据类型,参数类型不同的类

1.函数模板语法结构:

?templata <类型模板形参列表>类型模板形参 函数名(<形参列表>)

注意:

? ? ? ? ? ? ? ?templata:模板说明的关键字

? ? ? ? ? ? ? ? <类型模板形参列表>:用class或typename定义的变量,多个模板形参之间以空格隔开

? ? ? ? ? ? ? ? 1.class T1:定义类型模板形参 T1,用来代替函数的相关数据类型。

? ? ? ? ? ? ? ? eg:

? ? ? ? ? ? ? ? ? ? ? ? template<class T1>T1 add(T1 X,T1 Y);

把开头的例子用模板实现:

? ? ? ?

#include <iostream>
using namespace std;
template<typename T1>T1 add(T1 ,T1);//函数模板声明
template<class T1> //函数模板声明
T1 add(T1 x,T1 y) //函数模板定义
{
    return x+y;
}
int main()
{
    cout<<add(1,2)<<endl;
    cout<<add(3.1,2.3)<<endl; //函数模板的 隐式调用,自动匹配数据类型
    cout<<add('a','2')<<endl;
    return 0;
}

typename与class
原来C++只有class,但是对于初学者理解容易与类定义混淆
为了方便理解,后面的版本是加入了typename关键字方便教学使用,学校C++教材上有提过
有隐式调用就有显示调用

下面就是显示调用

#include <iostream>
using namespace std;
template<typename T1>T1 add(T1 ,T1);//函数模板声明
template<class T1> //函数模板声明
T1 add(T1 x,T1 y) //函数模板定义
{
    return x+y;
}
int main()
{
    cout<<add(1,2)<<endl;
    cout<<add(3.1,2.3)<<endl; //函数模板的 隐式调用,自动匹配数据类型
    cout<<add('a','2')<<endl;
    cout<<add<>(2,5)<<endl; //函数模板的显示调用
    cout<<add<int>(5,6)<<endl; //显示调用,指定模板性参 为int,是将int传递给了T1
    cout<<add<float>(3.12 ,4.1)<<endl;
    return 0;
}

如果是两个不同类型的数相加可以实现吗?

答案也是可以的。

例子:

#include <iostream>
using namespace std;
template<class T1,class T2> 
T1 add(T1 x,T2 y) 
{
    return x+y;
}
int main()
{
    cout<<add(2.1,2)<<endl;
    cout<<add<>(2,2.1 )<<endl;
    cout<<add<char,int>('a',1)<<endl;
    
    
    return 0;
}

还可以这样写在声明处定义,带默认参数的形参

#include <iostream>
using namespace std;
template<class T1,class T2=float> 
T2 add(T1 x,T2 y) 
{
    return x+y;
}
int main()
{
    cout<<add(2.1,2)<<endl;
    cout<<add<>(2,2.1 )<<endl;
    cout<<add<char,int>('a',1)<<endl;
    cout<<add<char>('b',2.1)<<endl;
    
    
    return 0;
}

自动匹配的优先级高于默认,因此模板形参的默认参数无意义。

存在即合理,当然也有他的用法,体现在这里

例:

#include <iostream>
using namespace std;
template<class T1,class T2,class T3=int> 
T3 add(T1 x,T2 y) 
{
    return x+y;
}
int main()
{
    cout<<add(2.1,2)<<endl;
    cout<<add<>(2,2.1 )<<endl;
    cout<<add<char,int>('a',1)<<endl;
    cout<<add<char>('b',2.1)<<endl;
    
    
    return 0;
}

注意返回值是T3,必须默认给T3类型,不然T3自己找不到类型。

如果不给默认类型,那么显示调用必须多给一个类型给T3。

例子:

#include <iostream>
using namespace std;
template<class T1,class T2,class T3> 
T3 add(T1 x,T2 y) 
{
    return x+y;
}
int main()
{
    cout<<add<char,int,int>('a',1)<<endl;
    
    
    return 0;
}

当然模板的作用不只是俩个值相加,我们再来看看别的用法。

例设计一个通用函数,函数功能,就是为指针开辟堆区空间,空间大小由使用函数时决定。

例子

#include <iostream>
#include <assert.h>
#define max 6
using namespace std;

/*
template<class T>   //模板一
T* newPoint(T ** p,int m)
{
    *p=new T[m];
    assert(NULL!=*p);
    return *p;
}
*/
template<class T,int m>//非类型模板形参:int m,用来替换函数模板中的常量值  T:类型模板型参,替换数据类型 m:非类型模板型参,替换常量值
T * newPoint()   
{
    T*p=new T[m];
    assert(NULL!=p);
    return p;
}
int main()
{
    char *p=nullptr;
    //newPoint(&p,max);
    //newPoint<char>(&p,max);
    p=newPoint<char,max>(); //调用的是第二个函数模板,元素个数由模板形参列表中 决定
    for(int i=0;i<max;i++)
    {
        cin>>p[i];
    }
    for(int i=0;i<max;i++)
    {
        cout<<p[i]<<" ";
    }
    cout<<endl;
    return 0;
}

tips:

?类class模板

1.如果一个类成为了模板那么这个类中所有成员函数将自动变成函数模板

类模板函数在内部实现

#include <iostream>
using namespace std;
template<class T>
class demo//声明定义一个类模板
{
    public:
        demo(T x):x(x){}
        void setvalue(T x)
        {
            this->x= x;
        }
        T getvalue()
        {
            return x;
        }
    private:
        T x;
};
int main()
{
    demo <int> obj(123);
    obj.setvalue(45);
    cout<<obj.getvalue()<<endl;
    return 0;
}

类模板函数在外部实现

#include <iostream>
using namespace std;
template<class T>
class demo//声明定义一个类模板
{
    public:
        /*
        demo(T x):x(x){}
        void setvalue(T x)
        {
            this->x= x;
       }
        T getvalue()
        {
            return x;
        }
        */
        demo(T x);
        void setvalue(T x);
        T getvalue();
    private:
        T x;
};
template<class A>
demo<A>::demo(A x):x(x){}
template<class B>
void demo<B>::setvalue(B X)
{
    this->x=X;
}
template<class C>
C demo<C>::getvalue()
{
    return x;
}
int main()
{
    demo <int> obj(23);  //类模板定义对象时,必须显示说明使用的类模板<>,并且必须传递数据类型
    obj.setvalue(45);
    cout<<obj.getvalue()<<endl;
    return 0;
}

类的非类型模板参数

#include <iostream>
using namespace std;
template<class T,int max>
class demo
{
    public:
        demo(T var);
        T getval(int);
    private:
        T arr[max];
};
template<class A ,int max>
demo<A ,max>::demo(A var)
{
    for(int i=0;i<max;i++)
    {
        arr[i]=var;
    }
}
template<class B ,int max>
B demo<B ,max >::getval(int id)
{
    if(id>=max)
    {
        ::exit(-1);
    }
    return arr[id];
}
int main()
{
    demo<int,6> obj(12);
    int id=0;
    cout<<obj.getval(id)<<endl;
    return 0;

tips:

构造函数析构函数没有返回值!

友元模板

类模板的友元成员函数在类外部定义时:

1.友元成员函数的定义和声明都必须使用template关键字单独说明

#include <iostream>
using namespace std;
template<class T>
class demo
{
    public:
        demo(T x):x(x){}
        template<class A>
        friend A operator+(demo<A> &a,demo<A> &b);
        /*
        {
            return a.x+b.x;
        }
        */
    private:
        T x;
};
template <class A>
A operator+(demo<A> &a,demo<A> &b)
{
    return a.x+b.x;
}
int main()
{

    demo<int> obj(2.1),obj1(3.2);
    cout<<obj+obj1<<endl;
    return 0;
}

?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-07-20 18:34:21  更:2022-07-20 18:36:45 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/13 20:29:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码