最近用的C++模板

最近写代码,发现很多代码都重复的出现,只是有细微的差别,之前用一个基类来做,但是发现有些地方需要根据类型来实例化。最后我想想就改用模板来实现了,之前对C++的模板只是有耳闻,但在实际项目中确很少去用。我把使用模板的时候需要的问题记录下来。

在项目中我总是遇到要写一些单例的东西,比如读取一些经常要用到的配置信息,我需要把他存在内存里面。这个时候我通常写一个单例,但是每次我都得写同样的代码,之前我就这么算了,每次写一遍,现在想想这样做重复的工作好吗,经过这次,我把它写成一个模板,因为有好几个地方需要用到。

我的单例模板:

#ifndef TEMPLATESINGLETON
#define TEMPLATESINGLETON

/**单例模板
 * @author zp
 * @date 2015-04-27
 */
template<typename T>
class Singleton
{
public:
    static T * getInstance()
    {
        static T instance;
        return &instance;
    }

public:
    Singleton(){}
    ~Singleton(){}
private:
    Singleton(const Singleton<T> &);
    Singleton& operator=(const Singleton<T> &);
};

#endif // TEMPLATESINGLETON

单例一般要把构造函数变成私有的,但是我把这个变成私有的时候,在继承的时候总是出现问题,改成公有就没有问题。

我在代码中是这样使用的

#include "TemplateSingleton.h"
#include <QMap>
#include <QString>

class AppConfig:public Singleton<AppConfig>
{
public:
    AppConfig();
    ~AppConfig();
public:
    QString getValueByKey(const QString& key);
private:
    bool loadFromAppConfigFile();
    bool loadFromFile(const QString& fileName);
private:
    QMap<QString,QString> mapValue;
};

#endif 

//调用就像其他单例一样调用
AppConfig::getInstance()->getValueByKey(“”);

具体实现就不说了,所有的都能够这么用,我感觉这让我写了好多代码,挺方便。

后来我在程序中另外一处也用了模板。。需求是这样的,我从一个webservice中获取数据,数据格式都是统一的。
我写了一个方法来获取webservice的数据,这个方法,之前在博客上写过。只是做了一些修改。这部分代码直接从我写的代码上拿过来,因为没有涉及到数据的定义,应该没什么问题。
不知道这个方式合不合适,但是现在用了,感觉还挺好

class BmilpManagerTemplate
{
public:
    BmilpManagerTemplate();
    virtual ~BmilpManagerTemplate();
public:
    /**
     * @brief addBmilpObj 添加对象
     * @param method  webservice方法
     * @param obj   对象
     * @return
     */
     static int addBmilpObj(const QString& method,const T & obj);


    /**
     * @brief updateBmilpObjById 通过Id更新数据
     * @param method webservice方法
     * @param newObj
     * @return
     */
     static int updateBmilpObj(const QString & method,const T & newObj);

     /** 根据id得到对象信息
      * @brief getBmilObjById
      * @param method 方法
      * @param paramStr 一般是"id"
      * @param id   id
      * @param newObj 对象
      * @return
      */
     static QString getBmilObjById(const QString& method, QString paramStr, int id, T & newObj);

     /**
      * @brief getAllBmilpObjList 获取所有数据,不分页
      * @param method
      * @param param
      * @param selObjList
      * @return
      */
     static QString getAllBmilpObjList(const QString & method,QMap<QString,QVariant> & param,QList<T*> & selObjList);

    /**
     * @brief getAllPageBmilpObjList 分页查询得到所有的数据
     * @param method
     * @param param
     * @param selObjList
     * @return
     */
     static QString getAllPageBmilpObjList(const QString & method,QMap<QString,QVariant> & param,QList<T*> & selObjList);
    /**
     * @brief selectBmilpObjListPage 分页查询
     * @param method
     * @param param
     * @param selObjList
     * @param pageCount
     * @param pageNo
     * @return
     */
     static QString getBmilpObjListPage(const QString & method,QMap<QString,QVariant> & param,QList<T*> & selObjList,int& pageCount,int & pageNo);
private:
    /**
     * @brief addupdateBmilpObj 添加和修改对象方法
     * @param method        webservice 方法
     * @param obj           对象
     * @param isUpdateFun   是否是更新方法
     * @return
     */
     static int addupdateBmilpObj(const QString & method,const T & obj,bool isUpdateFun=false);
};


#include "BmilpManagerTemplate.cpp"

// BmilpManagerTemplate.cpp文件按

template<typename T>
BmilpManagerTemplate<T>::BmilpManagerTemplate()
{

}


template<typename T>
BmilpManagerTemplate<T>::~BmilpManagerTemplate()
{

}



template<typename T>
int BmilpManagerTemplate<T>::addBmilpObj(const QString &method, const T &obj)
{
    return addupdateBmilpObj(method,obj,false);
}




template<typename T>
int BmilpManagerTemplate<T>::updateBmilpObj(const QString &method, const T &newObj)
{
    return addupdateBmilpObj(method,newObj,true);
}
template<typename T>
QString BmilpManagerTemplate<T>::getBmilObjById(const QString &method, QString paramStr, int id, T &newObj)
{
    BmilpWebServiceData data;
    QMap<QString,QVariant>  param;
    param.insert(paramStr,id);
    QNetworkReply::NetworkError netError = WebServiceHelp::getInstance()->sendGetRequest(method,param,data);
    if(netError ==QNetworkReply::NoError)
    {
        if(data.getCode() == WebServiceReturnCode::webServiceSuccessCode)
        {
            QMap<QString,QVariant> dataMap = data.getData().toMap();
            newObj.fromMap(dataMap);
        }
    }
    qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<<data.getMessage();
    return data.getCode();
}

template<typename T>
QString BmilpManagerTemplate<T>::getAllBmilpObjList(const QString & method,QMap<QString,QVariant> & param,QList<T*> & selObjList)
{

    BmilpWebServiceData data;

    QNetworkReply::NetworkError netError = WebServiceHelp::getInstance()->sendGetRequest(method,param,data);
    if(netError ==QNetworkReply::NoError)
    {
        if(data.getCode() == WebServiceReturnCode::webServiceSuccessCode)
        {
            if(data.getData().type()==QVariant::List)
            {
                QList<QVariant> dataList = data.getData().toList();
                foreach(QVariant var,dataList)
                {
                    T* pbType = new T();
                    QMap<QString,QVariant> dataMap = var.toMap();
                    pbType->fromMap(dataMap);
                    selObjList.append(pbType);
                }
            }
        }
    }
    qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<<data.getMessage();
   return data.getCode();
}



template<typename T>
QString BmilpManagerTemplate<T>::getAllPageBmilpObjList(const QString &method, QMap<QString, QVariant> &param, QList<T *> &selObjList)
{
     QString retCode = WebServiceReturnCode::webServiceFailCode;
    int pageNo = 1;
    int pageCount = 0;

    do
    {
        retCode = getBmilpObjListPage(method,param,selObjList,pageCount,pageNo);
        pageNo++;
    }while(pageNo<=pageCount);

    qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<<data.getMessage();
    return retCode;
}



template<typename T>
QString BmilpManagerTemplate<T>::getBmilpObjListPage(const QString &method, QMap<QString, QVariant> &param, QList<T *> &selObjList, int &pageCount, int &pageNo)
{
    QString retCode = WebServiceReturnCode::webServiceFailCode;
    BmilpWebServiceData data;
    QNetworkReply::NetworkError netError = WebServiceHelp::getInstance()->sendGetRequest(method,param,data);
    if(netError ==QNetworkReply::NoError)
    {
        if(jsonData.getCode()==WebServiceReturnCode::webServiceSuccessCode)
        {
            QVariantMap dataMap = data.getData().toMap();
            pageCount = dataMap.value("pageCount").toInt();
            pageNo  = dataMap.value("pageNo").toInt();
            retCode = data.getCode();
            QVariant result = dataMap.value("result");
            if(result.type() == QVariant::List)
            {
                QList<QVariant> resultList = result.toList();
                foreach(QVariant var,resultList)
                {
                    QMap<QString,QVariant> posData = var.toMap();
                    T * t = new T();
                    t->fromMap(posData);
                    selObjList.append(t);
                }
            }
        }
    }
    qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<<data.getMessage();
    return retCode;
}



template<typename T>
int BmilpManagerTemplate<T>::addupdateBmilpObj(const QString &method, const T &obj, bool isUpdateFun)
{
    int id = -1;
    QVariantMap param;
    QMap<QString,QVariant> dataMap = obj.toMap(isUpdateFun);
    QVariant var(dataMap);
    QJsonDocument jsonDoc = QJsonDocument::fromVariant(var);
    QByteArray ba = jsonDoc.toJson(QJsonDocument::Compact);
    qDebug()<<QString::fromUtf8(ba);
    BmilpWebServiceData jsonData;
    QNetworkReply::NetworkError netError = WebServiceHelp::getInstance()->sendPostRequest(method,param,ba,jsonData);
    if(netError==QNetworkReply::NoError)
    {
        if(jsonData.getCode()==WebServiceReturnCode::webServiceSuccessCode)
        {
            if(jsonData.getData().isValid())
            {
                bool OK = false;
                id = jsonData.getData().toInt(&OK);
                if(!OK)
                {
                    id = -1;
                }
            }
        }
    }
    qDebug()<<__FILE__<<__FUNCTION__<<__LINE__<<jsonData.getMessage();
    return id;
}

看看调用的地方吧:
因为模板里面有调用t->fromMap(posData); 所以t必须实现fromMap这个方法来初始化。
我程序设计里面这个t一定是我定义的object基类继承下来的,而且在基类里我把fromMap定义成了纯虚方法。
Type表示类型,obj表示对象
BmilpManagerTemplate::addBmilpObj(method,obj);
这样做我就不用吧每次调用webservice添加,重新写一遍,只是这么调用一下就解决了。
起始添加这个函数并不能体现模板的好,因为这个方法我之前用基类的方式就可以实现。
但是查询的时候不行,因为查询的时候我不能动态的知道类型,通过模板我就可以根据不同的类型给定不同的参数。

编写模板遇到的问题。之前我直接在工程里面建立的一个类,然后把方法写好,分别写在了两个不同的文件上,声明写在了头文件上,定义写在了cpp文件上,这样程序编译的时候老是出现错误,说某某函数为未找到。后来我翻了一下书籍,找到了答案。
我采取解决的办法是在头文件最后加入#include “BmilpManagerTemplate.cpp”
然后把cpp文件从工程中移除,因为模板需要在编译的时候就知道定义,所以必须让编译器知道定义,加了这个文件,起始可以把实现写到另一个头文件中这样更好。在代码中加入
include “BmilpManagerTemplate.cpp”感觉挺别扭。加了这句话后如果没有从工程中去掉.cpp文件的话,也会报错的,因为编译器会编译cpp文件,但是这个时候它是一个模板,没有具体的类型,所以会报错。去掉后编译就通过了,因为对模板的概念什么的都不熟,所以犯了很多错,很多错报的也莫名其妙不好找,花了不少时间,在此记下来。

扫描二维码关注公众号,回复: 875717 查看本文章

关于模板的问题,我想过段时间,我找本书系统的学习一下,把学习的笔记给记下来,现在只是用到哪记到哪。

很多时候我只是遇到了问题,然后去解决问题,并没有那么追根究底的去把一件事情弄得很透彻。以前怎么解决的也没有记录下来,所以遇到同样的问题。我又要做一遍原来要走的路,这样不知不觉在路上花了比别人多倍的时间。现在觉得应该把一些东西记下来,哪怕它再小。因为网络这东西谁说的准,今天本来可以查到的东西,明天就消失了。

猜你喜欢

转载自blog.csdn.net/zpbrook/article/details/45557621