C++,OpenCV 中template(模板)的简单理解

本文深入探讨了C++中的模板类与模板函数的概念及应用,通过类比的方法阐述了模板的意义,并给出了丰富的实例帮助理解。

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

  • 问题:为什么要写这篇博客呢?
    答:在看opencv 2.4.13 的手册的时候,有很多长得是这样的东东:
    这里写图片描述
    这里的 template<> class DataType< uchar> 是什么鬼呢?
    早期简单的百度了一下,是模板类。
    但是随着时间的推移,对模板的理解又有些模糊了,这里总结一下,以备后用。

  • 问题:为甚么要引入 模板?
    答:个人理解:为了避免重复劳动。
    下面利用本人对各种“瓶装水”的理解,进行类比。(可能不恰当)

名称内容作用
矿泉水解渴
功能饮料水+添加剂解渴
橙汁水+色素解渴
函数名输入参数函数的作用

从上表可以看出,不同的“瓶装水”在本人的眼中,其作用是相同的:解渴。只是名称不一样,输入的内容有些许差别。
这可以与函数的,函数名,输入参数,函数的作用。相类比。
因此:对于起到同一种作用的,输入参数类型不同的函数,我们可以用一个template来定义。可以大大减少工作量。
(因此,本人在买水时,从不纠结,只买矿泉水。)

  • 下面先借用这里对template的解释:
    这里写图片描述
    注:个人推荐在使用模板的时候,使用typename。
    下面给出例子:
template<typename T>
T min1(T a, T b){
    return (a<b)?a:b;
}
  • 问题:那里面的 typename 后面跟的 T 是什么意思?
    答:这个就是“替代类型”的意思,在调用的时候再替换成具体的类型,比如,int,double。
  • 问题:那么可以用其他字母替换 T么?
    答:当然可以,比如 你自己喜欢的任意一个字母或者字母的组合,比如:
template<typename REALLY>
REALLY min2(REALLY a, REALLY b){
    return (a<b)?a:b;
}
  • 问题:那我可以定义多种不同的“替代类型”么?
    答:当然可以,因为,函数的输入不会一定是同一种类型的啊,比如:
template<typename T, typename T2>
void show1(T a, T2 b){
    cout << "first value is: " << a <<endl;
    cout << "second value is: " << b <<endl;
}
  • 问题:可以对输入参数进行限定么?比如 加上 const?
    答:可以。事实上,一般函数定义中可以使用的东西,在这里都可以使用。
    比如:
template<typename T, typename T2>
void show2(const T a, T2 b){
    // a = 30; 这个将导致错误
    cout << "first value is: " << a <<endl;
    cout << "second value is: " << b <<endl;
}
  • 问题:说了这么多,好像和你刚开始提的问题并没有什么关系啊。
    答:刚开始的问题实际上是 “类模板”,上面描述的是“函数模板”。
    先说一下简单的,再搞复杂的。
    下面开始说,“类模板”。
    先给出例子:
// tc.h -- a class template

#ifndef _TC_H_
#define _TC_H_

template<typename T, typename T2>
class myC_1
{
public:
    myC_1();
    ~myC_1();
    void isBig(T value);
    void printS();
private:
    T  stock;
    T2 time;
};

template<typename T, typename T2>
myC_1<T,T2>::myC_1(){
    stock = 200;
    time = 90;
}


template<typename T, typename T2>
void myC_1<T,T2>::isBig(T value){
    if (stock > value)
        cout << "it it big. "<<endl;
}

template<typename T, typename T2>
myC_1<T,T2>::~myC_1(){
    stock = 0;
}

template<typename T, typename T2>
void myC_1<T,T2>::printS(){
    cout <<"value and time is: "<< stock <<" "<<time<<endl;
}


#endif

这里需要注意的:

  • 在每个成员函数的前面都要有这样一个声明
    template<typename T, typename T2>
  • 在每个成员函数定义的时候,都要有这样一个写法myC_1<T,T2>

是不是很麻烦。
但是,相对于重复写很多个类,这种方法相对简单多了。
下面,我们可以试着理解手册中的 关于 Mat 的 at 的用法了:
这里写图片描述
看最后一句H.at<double>(i,j)=1./(i+j+1);
这个其实是调用了第三个关于at的定义C++: template<typename T> T& Mat::at(int i, int j)
由于使用了模板,因此,在使用的时候,需要指定类型“double”
- 问题:为什这里的定义没有使用at<T>的形式呢?
答:这个,还要扯到 Mat_ ,类继承,等高深的问题。
我也不清楚呢。
- 问题:说道这里,和你开始提的那个问题还是有差距的呢。最开始的那个类的声明,用你的解释还是说不通啊。
答:这个,还有待进一步研究,也欢迎大牛指导。

恩,到这里,也就结束了了,不过没有解决最开始提出的问题。 mission failed。

放大招:整体代码:

// tc.h -- a class template

#ifndef _TC_H_
#define _TC_H_

template<typename T, typename T2>
class myC_1
{
public:
    myC_1();
    ~myC_1();
    void isBig(T value);
    void printS();
private:
    T  stock;
    T2 time;
};

template<typename T, typename T2>
myC_1<T,T2>::myC_1(){
    stock = 200;
    time = 90;
}


template<typename T, typename T2>
void myC_1<T,T2>::isBig(T value){
    if (stock > value)
        cout << "it it big. "<<endl;
}

template<typename T, typename T2>
myC_1<T,T2>::~myC_1(){
    stock = 0;
}

template<typename T, typename T2>
void myC_1<T,T2>::printS(){
    cout <<"value and time is: "<< stock <<" "<<time<<endl;
}


#endif
// csdn_code.cpp : 定义控制台应用程序的入口点。
//


#include "stdafx.h"
#include "tc.h"
#include <iostream>
#include <opencv2/opencv.hpp>


using namespace cv;
using namespace std;

template<typename T>
T min1(T a, T b){
    return (a<b)?a:b;
}

template<typename REALLY>
REALLY min2(REALLY a, REALLY b){
    return (a<b)?a:b;
}


template<typename T, typename T2>
void show1(T a, T2 b){
    cout << "first value is: " << a <<endl;
    cout << "second value is: " << b <<endl;
}


template<typename T, typename T2>
void show2(const T a, T2 b){
    // a = 30; 这个将导致错误
    cout << "first value is: " << a <<endl;
    cout << "second value is: " << b <<endl;
}




int main()
{

    int a = 3, b= 90;
    cout << "min is: " << min1(a,b)<<endl;

    double aa = 9.01, bb = 23.88;
    cout << "min is: " << min1(aa,bb)<<endl;

    cout << "min is: " << min2(aa,bb)<<endl;

    show1(a,aa);

    show2(aa,a);

    myC_1<int,int> s1;
    s1.isBig(30);
    s1.printS();


    waitKey();
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值