众所周知:全局变量存在着很多缺点:
全局变量的缺点:
长期占用内存:全局变量生命周期长,程序运行期一直存在,始终占有那块存储区;
难以定位修改:全局变量是公共的,全部函数都可以访问,难以定位全局变量在哪里被修改,加大了调试的难度;
使函数难以理解:使用全局变量的函数,需要关注全局变量的值,增加了理解的难度,增加了耦合性;
初始化顺序:全局变量的初始化顺序不定,如果全局变量之间有依赖,有可能导致某些变量初始化失败呢,引起莫名其妙bug。
污染命名空间:全局变量会污染命名空间,在函数中局部变量会覆盖全局的值,会出现同一个变量名多个值的情况,造成困惑;
增加耦合性:修改全部变量会影响所有用到它的模块,不利于调试;
线程不安全:多线程中多全局变量的修改容易冲突,需要加锁;
尤其是在多文件间的通信中,extern的使用会大大增加程序的耦合性,这在大型项目中是致命的,我们常常使用ROS等工具来解决这一通信问题,在这里给出一个仿照ROS的pub-sub通信机制的Transmission类来 实现无全局变量的多文件间通信。
这里以Bool型和opencv中的图片数据Mat型的数据为例,可以根据所需的数据类型自行调整。
新建Transmission.h,输入:
// Author: gyx
//This is used to define transmission class
#ifndef TRANSMISSION_H
#define TRANSMISSION_H
#include<string>
#include<functional>
#include<map>
#include<list>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/types_c.h>
using std::function;using std::string;using std::map;using std::list;
using cv::Mat;
typedef function<void(bool)>Callback_bool;
typedef function<void(Mat)>Callback_mat;
class Transmission
{
private:
Transmission() = default;
map<string,list<Callback_bool>>subscriber_bool;
map<string,list<Callback_mat>>subscriber_mat;
public:
static Transmission* getmessage();
void subscribe_bool(string eventType,Callback_bool callback);
void subscribe_mat(string eventType,Callback_mat callback);
void publish_bool(string eventType,bool data);
void publish_mat(string eventType,Mat src);
};
#endif //TRANSMISSION_H
新建Transmision.cpp,输入:
// Author: gyx
//This is used to establish a pub-sub system
#include<transmission.h>
Transmission* Transmission::getmessage(){
static Transmission messgae;
return &messgae;
}
//Transmit bool type data
void Transmission::subscribe_bool(string eventType,Callback_bool callback)
{
subscriber_bool[eventType].push_back(callback);
}
void Transmission::publish_bool(string eventType,bool data)
{
for(const auto& callback : subscriber_bool[eventType])
{
callback(data);
}
}
//Transmit Mat type data
void Transmission::subscribe_mat(string eventType,Callback_mat callback)
{
subscriber_mat[eventType].push_back(callback);
}
void Transmission::publish_mat(string eventType,Mat src)
{
for(const auto& callback : subscriber_mat[eventType])
{
callback(src);
}
}
此时,只需要在需要进行通信的文件中调用Transmission类即可,例:发布图片信息:
Transmission::getmessage()->publish_mat("Capture",CameraScreen);
这里给出Mat型的例子(这是我最近写的一个仿真程序的一部分):
// Author: gyx
//This is used to define the MapWidget class
#ifndef MAPWEIDGIT_H
#define MAPWEIDGIT_H
#include <QObject>
#include<QWidget>
#include<QTimer>
#include<car.h>
#include "transmission.h"
class Subscriber_capture
{
public:
CAR data;
Subscriber_capture(){
Transmission::getmessage()->subscribe_mat("Capture",[this](Mat src){this->recieve_video_event(src);});
}
void recieve_video_event(Mat src)
{
data.CameraScreen = src.clone();
}
};
class MapWidget : public QWidget
{
Q_OBJECT
protected:
void paintEvent(QPaintEvent *event);
//void keyPressEvent(QKeyEvent *event);
public:
MapWidget(QWidget *parent = 0);
QPoint start_point;
QPoint contro_point;
public slots:
void draw_map();
void draw_car();
void start_move();
void stop_move();
private:
QImage *m_img;
QImage *c_img;
QImage map_img;
bool if_start = 0;
Subscriber_capture subscriber_capture;
CAR car;
int time_count=0;
QTimer *timer=new QTimer();
CAR Car;
// QVector<bool> switch_vector;
};
#endif
这是图片的信息就已经发布并接受完成了。