C++语言之模版与类型转换

模版

C++的泛型编程

可以将数据类型作为参数进行传递

关键字:

C++模版的语法使用"<>"来表示泛型类型,并使用关键字template来定义和声明模版

分类:

模版函数

模版类

模版函数

语法:

template<class 假设的类型1,class 假设的类型2,.......>

template<typename 假设的类型1,typename 假设的类型2,.......>

返回值类型 函数名(形参列表)

{

函数体

}

注意:

当前函数中任何一处使用数据类型的地方都可以使用假设的类型

class 也可以替换为 typename

特点:

1,函数模版可以自动推导参数的类型,但是不会进行类型转换

2,函数模版可以自动类型推导,也可以显式指定类型

显式指定类型

函数名<指定的类型1,指定的类型2,...>(实参列表);

3,只能在声明的所在函数中使用

补充:

函数模板会经历两次编译:第一次是在加载时对函数模板本身进行编译,第二次是在函数被调用时,编译器根据所推导出来的 T 的类型,再次对函数模板进行编译,从而生成模板函数。

如:

template<class X,class Y>

Y add(X x,Y,x)

{

Y sum = (Y)(x+y);

return sum;

}

char a = add(1,'A');
如:

template<class X,class Y>

Y add(X x,Y,x)

{

Y sum = (Y)(x+y);

return sum;

}

char a = add<int,char>(1,'A');

模版函数与普通函数的区别

1,函数模版不允许自动类型转换,普通函数能够自动进行类型转换

2,函数模版和普通函数同时识别,优先使用普通函数,加<>强制使用函数模版

3,函数模版可以使用<>,普通函数不行

函数模版的局限性

#include <iostream>

using namespace std;

template <class T>

void method(T t)

{

cout<<t<<endl;

}

class A{};

int main()

{

method(10);

A a;

method(a);//此时模版可以推导出T的类型为A,但是A类没有重载<<运算符,所以无法通过cout输出,此时语法无错,但是无法编译生成可执行文件

return 0;

}

解决方法1:重载<<运算符

#include <iostream>

using namespace std;

template <class T>

void method(T t)

{

cout<<t<<endl;

}

class A{};

ostream& operator<<(ostream& out,A& a)

{

out<<"打印A的对象"<<endl;

return out;

}

int main()

{

method(10);

A a;

method(a);

return 0;

}

解决方法2:指定模版函数

#include <iostream>

using namespace std;

template <class T>

void method(T t)

{

cout<<t<<endl;

}

class A{};

//指定模版函数

template<> void method<A>(A a)

{

cout<<"打印A的对象"<<endl;

}

int main()

{

method(10);

A a;

method(a);

return 0;

}

类模版

概念:有模板的类

语法:

template<class 假设的类型1,class 假设的类型2,...>

class 类名:继承方式 父类名1,...

{

};

作用:当前类中任何一处使用数据类型的地方都可以使用假设的类型

创建对象:

类名<类型1,类型2,...> 对象名(实参列表);

类名<类型1,类型2,...> *对象名 = new 类名<类型1,类型2>(实参列表);

模版类作为父类

方案1:子类指明父类模版类型

方案2:子类也是模版类

模版类的函数声明与实现分离

注意

每一个类外实现的函数都是模版函数

template <class 假设的类型>

返回值类型 类名<假设的类型>::函数名(形参列表)

{

}
#include<iostream>

using namespace std;

template <class Q>

class Data

{

private:

Q q;

public:

Data();

Data(Q q);

Q getQ();

void setQ(Q q);

};

template <class x>

Data<x>::Data()

{

}

template<class Q>

Data<Q>::Data(Q q)

{

this->q = q;

}

template<class Q>

Q Data<Q>::getQ()

{

return q;

}

template<class Q>

void Data<Q> ::setQ(Q q)

{

this->q = q;

}

int main()

{

Data<int> data(10);

return 0;

}

hpp文件

因为模版类的声明与实现无法分离

故将模版类的声明与实现放在同一个文件中,该文件后缀名为.hpp

类模版对象作为形参

#include <iostream>

#include <iomanip>

// 类模板定义,模拟一个简单的数组类

template<typename T, int size>

class MyArray {

private:

T elements[size];

public:

MyArray() {}

// 给数组元素赋值的函数

void setElement(int index, T value) {

if (index >= 0 && index < size) {

elements[index] = value;

}

}

// 获取数组元素的函数

T getElement(int index) {

if (index >= 0 && index < size) {

return elements[index];

}

return T();

}

};

// 函数,以类模板MyArray的对象作为形参,计算数组中所有元素的和

template<typename T, int size>

T sumElements(MyArray<T, size> arr) {

T sum = T();

for (int i = 0; i < size; ++i) {

sum += arr.getElement(i);

}

return sum;

}

int main() {

// 实例化一个存储int类型元素,大小为5的MyArray对象

MyArray<int, 5> intArray;

for (int i = 0; i < 5; ++i) {

intArray.setElement(i, i + 1);

}

// 调用sumElements函数,传入MyArray对象,计算元素和并输出

int sum = sumElements(intArray);

std::cout << "The sum of elements in the array is: " << sum << std::endl;

return 0;

}

类型转换

C语言提供的强制类型转换
语法 :( 转换后的类型 ) 要转换的数据或变量

静态转换

static_cast<T>( 要转换的数据)

// 基本类型转换 支持
int num = static_cast < int > ( 3.14f );
// 基本指针类型转换 不支持
float f = 0.0f ;
//int *p1 = static_cast<int *>(&f);
// 上行转换 支持(安全)
Base * p2 = static_cast < Base *> ( new Son );
// 下行转换 支持(不安全)
Son * p3 = static_cast < Son *> ( new Base );
// 不相关类型转换 不支持
//Son *p4 = static_cast<Son *>(new Other);

动态类型转换

dynamic_cast<T>( 要转换的数据)
// 基本类型转换 不支持
//int num = dynamic_cast<int>(3.14f);
// 基本指针类型转换 不支持
float f = 0.0f ;
//int *p1 = dynamic_cast<int *>(&f);
// 上行转换 支持(安全)
Base * p2 = dynamic_cast < Base *> ( new Son );
// 下行转换 不支持(不安全)
//Son *p3 = dynamic_cast<Son *>(new Base);
// 不相关类型转换 不支持
//Son *p4 = dynamic_cast<Son *>(new Other);

常量转换

const_cast<T>
只能对指针与引用的变量使用

// 将非 const 转换成 const
int num = 10 ;
const int * p1 = const_cast < const int * > ( & num );
// 将 const 转换成 非 const
const int data = 0 ;
int * p = const_cast < int * > ( & data );

重新解释转换

这是最不安全的一种转换机制,最有可能出问题。
主要用于将一种数据类型从一种类型转换为另一种类型。它可以将一个指针转换成一个
整数,也可以将一个整数转换成一个指针.

语法:
reinterpret_cast<T>
// 基本类型转换 不支持
//int num = reinterpret_cast<int>(3.14f);
// 基本指针类型转换 支持
float f=0.0f;
int *p1 = reinterpret_cast<int *>(&f);
// 上行转换 支持(安全)
Base *p2 = reinterpret_cast<Base *>(new Son);
// 下行转换 支持(不安全)
Son *p3 = reinterpret_cast<Son *>(new Base);
// 不相关类型转换 支持
Son *p4 = reinterpret_cast<Son *>(new Other);

相关推荐
快意咖啡~9 分钟前
java.nio.charset.MalformedInputException: Input length = 1
java·开发语言·nio
李钢蛋13 分钟前
PHP函数---function_exists()详解
开发语言·php
刀鋒偏冷15 分钟前
ninja: error: ‘/opt/homebrew/Cellar/opensslxxx/xx/lib/libssl.dylib
c++
halo141619 分钟前
uni-app 界面TabBar中间大图标设置的两种方法
开发语言·javascript·uni-app
双手插兜-装高手26 分钟前
Linux - 线程基础
linux·c语言·笔记
froginwe1127 分钟前
Go 语言数组
开发语言
瑞雨溪28 分钟前
python中的OS模块的基本使用
开发语言·python
醒过来摸鱼32 分钟前
【Golang】协程
开发语言·后端·golang
时光追逐者33 分钟前
.NET 9 中 LINQ 新增功能实操
开发语言·开源·c#·.net·.netcore·linq·微软技术
Leuanghing34 分钟前
使用Python生成F分布表并导出为Excel文件
开发语言·python·excel·f分布