首页 > 编程语言 >C++语言之模版与类型转换

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

时间:2024-11-19 22:17:27浏览次数:3  
标签:类型转换 函数 int 模版 C++ cast template

模版

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);

标签:类型转换,函数,int,模版,C++,cast,template
From: https://blog.csdn.net/m0_75253775/article/details/143894852

相关文章

  • 《C++ 构建区块链:创世区块的初始化之道》
    在区块链这个神秘而充满魅力的技术领域中,用C++构建区块链是一项极具挑战性和创新性的工作。而其中,初始化创世区块是整个区块链大厦的基石,它承载着区块链的起源和根本属性,就像生命起源中的第一个细胞一样重要。今天,我们就来深入探讨一下在C++构建区块链时,如何进行创世区......
  • 《C++ 实现区块链:区块时间戳的存储与验证机制解析》
    在区块链这个复杂而精妙的技术架构中,时间戳是一个至关重要的元素,尤其当我们使用C++来实现区块链时,对区块时间戳的存储和验证机制设计更是不容忽视。这一机制如同区块链的时间脉搏,为整个系统的有序运行和数据可信性提供了坚实的保障。时间戳在区块链中的核心意义时间戳在......
  • 【优选算法篇】算法江湖中的碎玉拾光——C++模拟题全解,踏步逐章细细品味
    文章目录C++模拟题详解:基础题解与细致分析前言第一章:基础练习1.1替换所有的问号(easy)解法(模拟)C++代码实现易错点提示时间复杂度和空间复杂度1.2提莫攻击(easy)解法(模拟+分情况讨论)C++代码实现易错点提示时间复杂度和空间复杂度1.3N字形变换(medium)解法(模拟+找......
  • 嵌入式安卓开发使用LLDB进行断点调试C/C++代码
    GDBorLLDB?较新的安卓NDK已经没有包括gdbserver了,而且安卓官网也说了,后续不会支持gdb了。我自己之前费了很大的功夫,去交叉编译一个gdbserver,但最后用起来一大堆莫名其妙的问题。所以还是使用LLDB吧。获取相应的工具https://developer.android.google.cn/ndk/downloads这里下......
  • C++ Lambda表达式笔记
    1.什么是Lambda表达式?Lambda表达式是C++11引入的一种特性,允许定义匿名函数(没有名字的函数),并且可以像普通函数一样调用,甚至可以作为参数传递给其他函数。基本语法:[capture_list](parameters)->return_type{function_body};[capture_list]:捕获列表,决定外部变量如何......
  • C++语言之多态
    多态是面向对象编程中的一个重要概念,它是指同一个行为具有多个不同表现形式或形态的能力。比如,在不同的类中可以定义同名的方法,这些方法可以根据对象的类型不同而执行不同的逻辑。多态可以通过继承和接口实现,在继承关系中,子类重写父类的方法,当使用父类引用指向子类对象时,调用......
  • 【一分钟学C++】动态库与静态库
    竹杖芒鞋轻胜马,谁怕?一蓑烟雨任平生~公众号:C++学习与探索 | 个人主页:rainInSunny | 个人专栏:LearnOpenGLInQt文章目录动态库常见格式特点加载方式静态库常见格式特点动态库和静态库中的符号导出常见问题动态库常见格式  动态库是一......
  • C++虚函数表
    一、概念在C++中,虚函数表(VirtualFunctionTable,简称vtable)是实现多态机制的一个重要底层数据结构。当一个类中包含了虚函数时,编译器会为这个类创建一个虚函数表,用来存放该类的虚函数的地址。每个包含虚函数的类的对象实例中,会隐含一个指针(通常称为虚指针,vptr),它指向所属类......
  • 什么是 C++ 中的友元函数和友元类?友元的作用是什么?有什么注意事项?
    友元函数定义友元函数是在类中声明的非成员函数,它可以访问类的私有(private)和保护(protected)成员。友元函数虽然不是类的成员函数,但它被授予了访问类内部成员的特殊权限。声明方式在类的定义中,使用friend关键字来声明友元函数。classMyClass{private:intprivateDat......
  • c++等级考试第8级第2卷
                                       道路(2024.3八级)代码#include<iostream>#include<algorithm>#include<cmath>#include<cstdio>#include<vector>#include<cstring>usingnamespacestd;st......