花一点时间深入C++吧(1)
在分析opencv代码的时候,可以发现很多问题的解决都离不开class,template
并且计算机视觉的很多工程文件都需要调用第三方库(比如g2o),在实际编程中,需要自己去写接口(模仿别人的sample或者demo),有时候为了写一个好用的接口,需要自己去构造一个类或者结构体
然而,C++Primer里面介绍了过于全面,不宜学习,再说也没有必要全部学习
只要把相关的,常见的知识点学到,就可以啦
我不是想从教科书的角度去讲东西,我想从自己的研究过程说说对这些抽象数据结构的理解
那就先从“类”说起吧,比如opencv中的一个常见类kalman,
class CV_EXPORTS_W KalmanFilter { public: /** @brief The constructors. @note In C API when CvKalman\* kalmanFilter structure is not needed anymore, it should be released with cvReleaseKalman(&kalmanFilter) */ CV_WRAP KalmanFilter(); /** @overload @param dynamParams Dimensionality of the state. @param measureParams Dimensionality of the measurement. @param controlParams Dimensionality of the control vector. @param type Type of the created matrices that should be CV_32F or CV_64F. */ CV_WRAP KalmanFilter( int dynamParams, int measureParams, int controlParams = 0, int type = CV_32F ); /** @brief Re-initializes Kalman filter. The previous content is destroyed. @param dynamParams Dimensionality of the state. @param measureParams Dimensionality of the measurement. @param controlParams Dimensionality of the control vector. @param type Type of the created matrices that should be CV_32F or CV_64F. */ void init( int dynamParams, int measureParams, int controlParams = 0, int type = CV_32F ); /** @brief Computes a predicted state. @param control The optional input control */ CV_WRAP const Mat& predict( const Mat& control = Mat() ); /** @brief Updates the predicted state from the measurement. @param measurement The measured system parameters */ CV_WRAP const Mat& correct( const Mat& measurement ); CV_PROP_RW Mat statePre; //!< predicted state (x'(k)): x(k)=A*x(k-1)+B*u(k) CV_PROP_RW Mat statePost; //!< corrected state (x(k)): x(k)=x'(k)+K(k)*(z(k)-H*x'(k)) CV_PROP_RW Mat transitionMatrix; //!< state transition matrix (A) CV_PROP_RW Mat controlMatrix; //!< control matrix (B) (not used if there is no control) CV_PROP_RW Mat measurementMatrix; //!< measurement matrix (H) CV_PROP_RW Mat processNoiseCov; //!< process noise covariance matrix (Q) CV_PROP_RW Mat measurementNoiseCov;//!< measurement noise covariance matrix (R) CV_PROP_RW Mat errorCovPre; //!< priori error estimate covariance matrix (P'(k)): P'(k)=A*P(k-1)*At + Q)*/ CV_PROP_RW Mat gain; //!< Kalman gain matrix (K(k)): K(k)=P'(k)*Ht*inv(H*P'(k)*Ht+R) CV_PROP_RW Mat errorCovPost; //!< posteriori error estimate covariance matrix (P(k)): P(k)=(I-K(k)*H)*P'(k) // temporary matrices Mat temp1; Mat temp2; Mat temp3; Mat temp4; Mat temp5; };
类kalman核心的接口函数是prediect和correct。接口是什么?百度上是这样解释的:
接口泛指实体把自己提供给外界的一种抽象化物(可以为另一实体),用以由内部操作分离出外部沟通方法,使其能被内部修改而不影响外界其他实体与其交互的方式
我想换一个角度讲,如果不用类,可不可以写出函数predect和correct呢?答案是可以的。那为什么封装成一个类呢?封装成为类方便他人使用。比如你写了kalman的程序。你的好朋友小明正好也需要用kalman做预测,但是他很懒,不想自己写,他知道你写了一个,于是对你说能不能把你的程序借他一看。如果你把kalman封装起来,就只需要给他kalman.cpp以及kalman.h就行了,无需把你全部程序都发给他。小明只需要把kalman.cpp以及kalman.h通过编译器链接到他的程序,就可以使用你的程序了。
假设你没有把kalman封装起来,那么小明再看你几百行的程序的时候,就得把kalman相关部分“扣”出来,放到他的程序里。因此,类的引进极大地方便了“程序的交互使用”。
类的前身是“函数”,比如写了一个求解一元二次方程的函数,以后再求解问题的时候,不必每次都写,只需要调用函数就行了。
可是当一个问题变得非常复杂的时候,比如非线性优化,往往一个问题的求解需要调用几十个函数以及数十个变量的时候,就需要一个更大的“容器”把他们存放起来,方便其他人亦或自己使用。
在C++Primer中讲到,最好把类的使用者以及类的设计者区分开来。因为要想开发一款成功的应用程序,棋作者必须充分了解并实现用户的需求。同样,优秀的类设计者也应该密切关注那些有可能使用该类的程序员的需求。作为一个设计优良的类,既要有直观且易于使用的接口,也必须具有高效的实现过程
这些话很中肯!