类模板 --- 下 --- 特化、模板参数、智能指针

本文介绍了C++中类模板的使用方法,包括类模板的局部特化和非类型模板参数的应用。并通过具体实例展示了如何利用类模板实现高效计算及智能指针的设计,以解决内存管理和操作中的常见问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

类模板的局部特化

类模板可以定义多个类型参数。
如下图所示:
这里写图片描述

类模板可以被局部特化

可以指定类模板的特定实现,并要求某些类型参数仍然必须得模板的用户指定。

编译器会优先选择经过特化的类模板。

这里写图片描述

为什么需要特化,而不重新定义新类?
特化和重新定义新类看上去没有本质区别,但是如果定义新类,那么将变成一个类模板和一个新类,使用的时候需要考虑究竟是用类模板还是用新类。
而特化可以统一的方式使用类模板和特化类,编译器自动优先选择特化类。

非类型模板参数

函数模板和类模板的模板参数可以是普通数值。

这里写图片描述

非类型模板参数与特化,代码实例:

//采用类模板和特化类实现从1加到100
#include <cstdlib>
#include <iostream>
using namespace std;

//本代码求1-n相加的和,不分配空间,不调用函数,效率高 

template<int N>//类模板
class Sum
{
public:
    static const int VALUE = Sum<N - 1>::VALUE + N;
    // static表明是静态成员变量   
    // const表明这是常量会被放到符号表中,不会分配空间 
    // 在编译的过程中就已完成了递归  
    // 编译器完成了计算,在程序执行的时候不再花费时间 
};

template<>   //特化类,没有特化类,递归就无法结束
class Sum<1>
{
public:
    static const int VALUE = 1;
};

int main(int argc, char *argv[])
{
    cout<<Sum<10>::VALUE<<endl;
    cout<<Sum<100>::VALUE<<endl;

    cout<<sizeof(Sum<100>)<<endl;//大小为 1 字节 

    cout << "Press the enter key to continue ...";
    cin.get();
    return EXIT_SUCCESS;
}

非类型模板参数的限制:

变量不能作为模板参数。
浮点数和类对象不能作为模板参数。
全局指针不能作为模板参数。

只有整形作为模板参数比较安全。

编译器的推导过程是在编译阶段完成的。因此,编译器的推导必须依赖于特化类,否则推导过程无法结束。当没有定义特化类时,编译就会报错。

工程问题

在实际工程中内存操作是bug的重要来源C++将堆内存交由程序员自由使用,因此有如下的几种bug:
1、未及时释放,将产生内存泄漏
2、重复释放同一段内存,行为未知
3、使用越界,操作了不属于自己的内存

内存越界的问题常发生于数组的使用中。
解决方案:数组类
工程中,在非特殊情况下,要求开发者使用预先编写的数组类对象代替C语言中的原生数组。

内存泄漏内存多次释放常发生于指针的使用过程中。
解决方案:智能指针
工程中,要求开发者使用预先编写的智能指针类对象代替C语言中的原生指针。

智能指针 smart point

工程中的智能指针是一个类模板

  • 通过构造函数接管申请的堆内存。
  • 通过析构函数确保堆内存被及时释放。
  • 通过重载指针运算符 * 和 -> 模拟指针的行为。
  • 通过重载比较运算符 == 和 != 模拟指针的比较。

智能指针的创建与使用,代码举例:

//智能指针 类定义 头文件 SmartPoint.h
#ifndef _SMARTPOINTER_H_
#define _SMARTPOINTER_H_

template<typename T> //类模板 
class SmartPointer
{
protected:
    T* m_pointer;
public:
    SmartPointer();
    SmartPointer(const T* pointer);
    ~SmartPointer();
    T* operator->();
    T& operator*();
    bool operator==(const SmartPointer<T>& operater);
    bool operator!=(const SmartPointer<T>& operater);
};

#endif
//智能指针 类成员函数定义 头文件 SmartPoint.hpp
#ifndef _SMARTPOINTER_DEF_H_
#define _SMARTPOINTER_DEF_H_

#include "SmartPointer.h"

template<typename T>
SmartPointer<T>::SmartPointer()//构造函数 
{
    m_pointer = NULL;
}

template<typename T>
SmartPointer<T>::SmartPointer(const T* pointer)//构造函数 
{
    m_pointer = const_cast<T*>(pointer);
}

template<typename T>
SmartPointer<T>::~SmartPointer()//析构函数 
{
    delete m_pointer;
}

template<typename T>
T* SmartPointer<T>::operator->()//操作符重载 
{
    return m_pointer;
}

template<typename T>
T& SmartPointer<T>::operator*()//操作符重载 
{
    return *m_pointer;    
}    

template<typename T>
bool SmartPointer<T>::operator==(const SmartPointer<T>& operater)
{
    return m_pointer == operater.m_pointer;
}

template<typename T>
bool SmartPointer<T>::operator!=(const SmartPointer<T>& operater)
{
    return m_pointer != operater.m_pointer;
}

#endif
//智能指针 main文件 main.cpp
#include <cstdlib>
#include <iostream>
#include "SmartPointer.hpp"
using namespace std;

class Test
{
public:
    int i;
    void print()
    {
        cout<<i<<endl;
    }
};

int main(int argc, char *argv[])
{
    SmartPointer<int> pi (new int(5));//构造函数 
    SmartPointer<Test> pt (new Test());
    SmartPointer<int> pj = pi;

    cout<<*pi<<endl;

    *pi = 10;//使用重载操作符 

    cout<<*pi<<endl;

    pt->i = 20;//使用重载操作符
    pt->print();

    if (pi != pj)//使用重载操作符
    {
        cout<<"!="<<endl;
    }
    else
    {
        cout<<"=="<<endl;
    }

    cout << "Press the enter key to continue ...";
    cin.get();
    return EXIT_SUCCESS;
}

小结

类模板中可以有一个或多个未指定的泛指类型。
可以在需要的特化类模板。
特化可以统一的方式使用类模板和新定义的类。
特化类总是被编译器优先选择使用。
模板的参数可以是普通数值。
数组类和智能指针可以最大限度的避免内存相关的bug。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值