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

来源:互联网 发布:单片机智能反编译器 编辑:程序博客网 时间:2024/05/17 08:57
  • 问题:为什么要写这篇博客呢?
    答:在看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;}
原创粉丝点击