C++ 关于回调函数调用具类中的函数

近期工作中用到回调函数,回调函数是C语言中的概念,在C++中使用回调函数回破坏类及其对象的封装性。但是有的时候也要使用一下,那怎么办呢?

也就是把需要回调的函数定义成静态函数的形式调用:(QT5.7)

设计到两个类:
GeoTree:自定义的树形控件,主要用来显示图像要素
GeoManager:主要用来管理图形要素的,包括添加、删除、修改绘制等。
以下只是列出了部分代码,并没有贴出全部代码,主要是为了演示,如何回调类中的函数。采用的主要思想就是调用另外一个类的静态函数,并且传递类对象指针的形式实现。仅供参考。

GeoTree.h

class GeoTree : public QTreeWidget {
    Q_OBJECT

public:
    GeoTree(QWidget *parent);
    ~GeoTree();

    static void callbackNewGeo(GeoTree*treeWidget,GEO_TYPE type);
private:
    void init();
    void initTree();
public:
    QTreeWidgetItem* pointRootItem;   //点
    QTreeWidgetItem* lineRootItem;    //线
    QTreeWidgetItem* polygonRootItem; //多边形
    QTreeWidgetItem* rectRootItem;    //矩形
    QTreeWidgetItem* circleRootItem;  //圆
};

GeoTree.cpp

#include "stdafx.h"
#include "GeoTree.h"
#include "GeoDrawDef.h"
#include "GeoManager.h"

GeoTree::GeoTree(QWidget *parent)
: QTreeWidget(parent) {
    init();
}

GeoTree::~GeoTree() {
}

//初始化
void GeoTree::init() {

    this->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(this, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(slotRClick(QPoint)));
    connect(this, SIGNAL(itemPressed(QTreeWidgetItem*, int)), this, SLOT(slotPressItem(QTreeWidgetItem*)));

    initTree();

    theGeoType = GEO_TYPE_NULL;
    GeoManager::getInstance()->setInvokeNewGeo(this, GeoTree::callbackNewGeo);
}

//初始换树形控件
void GeoTree::initTree() {
    pointRootItem = new QTreeWidgetItem(this, QStringList(gGeoDrawType[0]));
    pointRootItem->setData(0, Qt::UserRole, QVariant(GEO_TYPE_POINT));
    this->addTopLevelItem(pointRootItem);

    lineRootItem = new QTreeWidgetItem(this, QStringList(gGeoDrawType[1]));
    lineRootItem->setData(0, Qt::UserRole, QVariant(GEO_TYPE_LINE));
    this->addTopLevelItem(lineRootItem);

    polygonRootItem = new QTreeWidgetItem(this, QStringList(gGeoDrawType[2]));
    polygonRootItem->setData(0, Qt::UserRole, QVariant(GEO_TYPE_POLYGON));
    this->addTopLevelItem(polygonRootItem);

    rectRootItem = new QTreeWidgetItem(this, QStringList(gGeoDrawType[3]));
    rectRootItem->setData(0, Qt::UserRole, QVariant(GEO_TYPE_RECT));
    this->addTopLevelItem(rectRootItem);

    circleRootItem = new QTreeWidgetItem(this, QStringList(gGeoDrawType[4]));
    circleRootItem->setData(0, Qt::UserRole, QVariant(GEO_TYPE_CIRCLE));
    this->addTopLevelItem(circleRootItem);
}

//静态回调函数-新建图形的时候调用
void GeoTree::callbackNewGeo(GeoTree*treeWidget, GEO_TYPE type) {
    switch (type) {
        case GEO_TYPE_NULL:
        break;
        case GEO_TYPE_POINT:{
            QString name = GeoManager::getInstance()->getCurrentPoint()->name;
            QTreeWidgetItem* pointItem = new QTreeWidgetItem(treeWidget->pointRootItem, QStringList(name));
            treeWidget->pointRootItem->setExpanded(true);

            break;
        }
        case GEO_TYPE_LINE:{
            QString name = GeoManager::getInstance()->getCurrentLine()->name;
            QTreeWidgetItem* lineItem = new QTreeWidgetItem(treeWidget->lineRootItem, QStringList(name));
            treeWidget->lineRootItem->setExpanded(true);
            break;
        }
        case GEO_TYPE_POLYGON:{
            QString name = GeoManager::getInstance()->getCurrentPolygon()->name;
            QTreeWidgetItem* polygonItem = new QTreeWidgetItem(treeWidget->polygonRootItem, QStringList(name));
            treeWidget->polygonRootItem->setExpanded(true);
            break;
        }
        case GEO_TYPE_RECT:{
            QString name = GeoManager::getInstance()->getCurrentRect()->name;
            QTreeWidgetItem* rectItem = new QTreeWidgetItem(treeWidget->rectRootItem, QStringList(name));
            treeWidget->rectRootItem->setExpanded(true);
            break;
        }
        case GEO_TYPE_CIRCLE:{
            QString name = GeoManager::getInstance()->getCurrentCircle()->name;
            QTreeWidgetItem* circleItem = new QTreeWidgetItem(treeWidget->circleRootItem, QStringList(name));
            treeWidget->circleRootItem->setExpanded(true);
            break;
        }
        default:
        break;
    }
}

GeoManager.h

#pragma once
#include "GeoDrawDef.h"
#include <vector>
using namespace std;
class QPaintEvent;
class GeoTree;

//声明回调函数
typedef void(*pNewGeo)(GeoTree* tree, GEO_TYPE type);

class GeoManager {
protected:
    GeoManager();
public:
    ~GeoManager();

public:
    static GeoManager* getInstance();//获取单例

    void addGeo(GeoPoint* geoPt);
    void addGeo(GeoLine* geoLine);
    void addGeo(GeoPolygon* geoPolygon);
    void addGeo(GeoRect* geoRect);
    void addGeo(GeoCircle* geoCircle);
    void setInvokeNewGeo(GeoTree* tree, pNewGeo newGeo);

private:
    static GeoManager* instance;
    pNewGeo addNewGeo;
    GeoTree* treeWidget;
};

GeoManager.cpp

#include "stdafx.h"
#include "GeoManager.h"
#include "CoordManager.h"
#include "Map\MyMap.h"
#include <QVector.h>

GeoManager* GeoManager::instance = new GeoManager;

GeoManager::GeoManager() {
}

GeoManager::~GeoManager() {
}

GeoManager* GeoManager::getInstance() {
    return instance;
}

//添加点要素
void GeoManager::addGeo(GeoPoint* geoPt) {
    pointList.push_back(geoPt);
    currentPoint = pointList.size() - 1;
    addNewGeo(treeWidget, currentGeoType);
}

//添加线
void GeoManager::addGeo(GeoLine* geoLine) {
    lineList.push_back(geoLine);
    currentLine = lineList.size() - 1;
    addNewGeo(treeWidget, currentGeoType);
}

//添加多边形要素
void GeoManager::addGeo(GeoPolygon* geoPolygon) {
    polygonList.push_back(geoPolygon);
    currentPolygon = polygonList.size() - 1;
    addNewGeo(treeWidget, currentGeoType);
}

//添加矩形要素
void GeoManager::addGeo(GeoRect* geoRect) {
    rectList.push_back(geoRect);
    currentRect = rectList.size() - 1;
    addNewGeo(treeWidget, currentGeoType);
}

//添加圆元素
void GeoManager::addGeo(GeoCircle* geoCircle) {
    circleList.push_back(geoCircle);
    currentCircle = circleList.size() - 1;
    addNewGeo(treeWidget, currentGeoType);
}

//添加圆心点
void GeoManager::addCircleCenter(double lon, double lat, double alt) {
    circleList[currentCircle]->centerLon = lon;
    circleList[currentCircle]->centerLat = lat;
    circleList[currentCircle]->centerAlt = alt;
}

//设置回调函数
void GeoManager::setInvokeNewGeo(GeoTree* tree, pNewGeo newGeo) {
    treeWidget = tree;
    addNewGeo = newGeo;
}

下图就展示了,当我创建一个图像元素的时候,在左侧的树形控件中就会显示出对应的节点来。当然还用多种方法实现,本文采用的回调函数的方式实现。
这里写图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wb175208

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值