这不是一篇纯技术文章,文末有煽情。
先解决技术问题。
在项目中我开发后端采集程序。项目开始,我使用的红外相机类型是CX320,后来因为某些原因不得不换同一个牌子的其他类型相机CG640。这两款相机使用的SDK是一样的,但是两款相机使用的具体函数不一样。
这两个相机有两点不一样:
-
采集的图片大小不一样,一个是320*240,一个是640*480;
-
采集红外数据的具体函数不一样,更直观的表达是相机型号不一样,一个是A型号,另一个是B型号。
而实际中,A型号中有320*240和640*480两种,B型号中也有这两种。细分相当于有四种相机,现在要求用一个版本就能解决四个不同相机采集的问题。那如何解决传入某一种型号的相机,程序就能自动判断调用属于该类型相机的函数呢?
解决方法:使用类的派生特性可以解决这个问题。根据传入不同的相机类型,派生相对应的对象,通过对象调用对应相机的函数。
我将这个问题分成两个部分。
01 如何做到调用属于特定相机的特定函数?
基类CoxInfraCam定义如下:
class CoxInfraCam
{
public:
CoxInfraCam();
explicit CoxInfraCam(const int _width, const int _height);
virtual ~CoxInfraCam();
public:
virtual bool InitialCamera();
virtual bool ConnectCamera();
virtual bool DisconnectCamera();
virtual bool StartCapture();
virtual bool StopCapture();
virtual bool DiffrentFun1();
virtual bool DiffrentFun2();
virtual bool DiffrentFun3();
}
注:DiffrentFun的命名只是为了区分,并不是实际程序中的命名。*
最下面的三个函数DiffrentFun1、DiffrentFun2和DiffrentFun3,不同的相机实现方法不一样。所以把这个三个函数设置为虚函数,这样就可以在派生类中更改这三个函数。基于类CoxInfraCam派生了两个类CXInfraCam和CGInfraCam,声明和实现如下:
CXInfraCam类声明
class CXInfraCam :
public CoxInfraCam
{
public:
CXInfraCam();
explicit CXInfraCam(const int _width, const int _height);
~CXInfraCam();
virtual bool DiffrentFun1();
virtual bool DiffrentFun2();
virtual bool DiffrentFun3();
private:
int m_iWidth_;
int m_iHeight_;
};
CXInfraCam类实现
CXInfraCam::CXInfraCam(const int _width, const int _height) :CoxInfraCam(_width, _height)
{
m_iWidth_ = _width;
m_iHeight_ = _height;
}
bool CXInfraCam::DiffrentFun1() {……}
bool CXInfraCam::DiffrentFun2() {……}
bool CXInfraCam::DiffrentFun3() {……}
CGInfraCam类声明
class CGInfraCam :
public CoxInfraCam
{
public:
CGInfraCam();
explicit CGInfraCam(const int _width, const int _height);
~CGInfraCam();
virtual bool DiffrentFun1();
virtual bool DiffrentFun2();
virtual bool DiffrentFun3();
private:
int m_iWidth_;
int m_iHeight_;
};
CGInfraCam类实现
CGInfraCam::CGInfraCam(const int _width, const int _height) : CoxInfraCam(_width, _height)
{
m_iWidth_ = _width;
m_iHeight_ = _height;
}
bool CGInfraCam::DiffrentFun1() {……}
bool CGInfraCam::DiffrentFun2() {……}
bool CGInfraCam::DiffrentFun3() {……}
从上面两个类的定义可以看到只需要修改DiffrentFun*就可以,其他的函数都从基类CoxInfraCam中继承。
例如现在new了类CXInfraCam的对象。
CoxInfraCam* pThis = new CXInfraCam(width, height);
//指向派生类的基类指针,可以调用派生类中修改过的虚函数
在new新对象的过程中,调用构造函数CXInfraCam(const int _width, const int _height),同时还调用父类的构造函数CoxInfraCam(_width, _height)。这一做法就能解决调用属于特定相机的特定函数。
02 如何根据传入相机类型生成该类型的对象。
我先定义了一个枚举类型作为传入的参数。
typedef enum{
TYPE_CX320 = 0,
TYPE_CX640 = 1,
TYPE_CG320 = 2,
TYPE_CG640
}COXCAMTYPE;
这个类型表示了有四种不同类型的相机。
然后根据传入的不同参数,new不同的相机对象,看代码更加直观一些。
void* _stdcall CIn_IRCam_CreateObject(COXCAMTYPE _coxType)
{
int width;
int height;
CoxInfraCam* pThis = NULL;
switch (_coxType)
{
case TYPE_CX320:
width = 320;
height = 240;
pThis = new CXInfraCam(width, height);
break;
case TYPE_CX640:
width = 640;
height = 480;
pThis = new CXInfraCam(width, height);
break;
case TYPE_CG320:
width = 320;
height = 240;
pThis = new CGInfraCam(width, height);
break;
case TYPE_CG640:
width = 640;
height = 480;
pThis = new CGInfraCam(width, height);
break;
default:
pThis = NULL;
break;
}
return pThis;
}
上面的内容只写出了解决这个问题的关键部分。
在项目的末尾,突然说要换相机确实是让人抓狂的。有经验的人能够马上想出比这更好的解决方案,可能它只需要花上10分钟时间就能想透想明白。而我遇到这个问题的时候,我一共改了三版代码,累计时间至少三小时。
1.马上更改CX320所在工程的函数,重新调试。
已经没办法冷静思考了,时间不多,并且两个相机不同的函数并不多,花不了多长时间就能改出来。所以马上在修改原有工程的代码。
2.更改CoxInfraCam类的实现,传入camera type参数,增加一个switch的语法,根据这个参数选择CX320或者CG640。
既然两个相机大部分实现代码都是一样的,那我就传入不同相机类型,根据类型去调用相应的函数,马上想到switch语句。
3.把CoxInfraCam当作一个基类,分别派生出属于CX320的CXInfraCam和属于CG640的CGInfraCam。在对应的类里面增加相应的函数。
该处上一版代码之后,这个项目也没那么赶了,有足够的时间去思考。确实我发现好像还有更灵活不像上面两种那么机械的方法。
真正的知识确实是在具体项目中获取到的。研究生期间读《C++ primer Plus 第五版》的时候,内心极度痛苦,读这样的技术书籍真的很枯燥,字全都认识可就是不明白作者说的是什么。每天即便花上四五小时去读这本书,找工作的时候可能还是什么都不懂。那段时间,一直不能静下心来认真看这本书,也不知道自己到底怎么了,怎么就静不下心来。
没有项目依托去学C++真的是浪费生命,即便花了很长时间去学,你了解地可能也不会深入。那怎么办?很多人想做软件开发,却发现自己的导师是镀膜的,怎么办?你要做的是先去了解用C++可以做什么样的开发,然后再去网上找项目,看别人的代码,再模仿别人的代码。模仿是提升代码能力的最最有效的途径,这确实是我个人最深切的体会。
2016年10月去臻识面试的时候,公司总经理问我有没写过一个类,我说写过,这个类是把所有的关于计算的函数放在一起。总经理只是笑了笑,最后给我的回复是:我不会跟你签正式的三方协议,可以考虑让你实习一段时间,看你表现再签。很显然,我根本不知道什么是类,什么是C++。虽然读研期间,每天都在写都在用,但是从来未想过为什么是这样写,还有没其他写法?
后来在臻识实习的三个月里,我的自信被打击了,我也开始认为我自己能力不行,我也认为自己做不了软件开发。接下来就是转岗,再接下来就是我人生中黑暗的十个月(这句话也只是基于我个人价值观进行评判,于公司及岗位无关):转到技术支持,全国到处跑。一度怀疑人生,找不到人生的意义。
终究我还是变成了更好的我,谢谢臻识,愿好!