背景:
最近小学期做C++课设,题目是【学生成绩录入系统】(用到了QT多窗口界面)。
因为要在多个窗口之间共享学生信息,所以需要完成多个类之间共享同一份数据的功能。
方法:
直接使用下面的代码即可:
头文件 datashare.h:
#ifndef DATASHARE_H
#define DATASHARE_H
#include "grade.h" // 需要共享的数据(在这里是“Grade”类的一个对象)的头文件定义
class DataShare {
protected: // 禁止类外访问,但允许子类访问
DataShare(); // 构造函数,初始化要共享的数据
Grade& grade = sharedData(); // 定义要共享数据的引用(可被修改)
private: // 禁止类外和子类访问
static Grade& sharedData(); // 返回要共享数据的引用(可被修改)
};
#endif // DATASHARE_H
实现文件 datashare.cpp:
#include "datashare.h"
DataShare::DataShare() { // 初始化要共享的数据,这部分因人而异
this->sharedData() = Grade(); // 一定要赋值给 “this->sharedData()”
this->sharedData().loadJsonFile(":/grade.json");
}
Grade& DataShare::sharedData() { // 返回要共享数据的引用(可被修改)
static Grade dataShare; // 这里是真正要共享的数据本体
return dataShare;
}
说明:
① 在上面的代码中,datashare是需要共享的数据(datashare是Grade类的实例,其中存放了整个年级的数据),这部分需要修改为你要共享的实例,也可以是其他任何类型的数据。
② 必须在构造函数中初始化你需要共享的对象/数据。
③ 共享方法:假如需要在A、B、C类之间共享数据grade,只需要A、B、C类同时继承于DataShare类即可,然后就能在A、B、C类里面直接使用DataShare类的grade成员(就像是自己的成员一样)
举例:
现在有4个窗口需要共享整个年级的数据(存放于grade对象,而grade对象存放于DataShare类中),那么只需要像下面这样分别继承于DataShare类即可:
class AddWindow : public QWidget, protected DataShare
class MainWindow : public QMainWindow, protected DataShare
class ManageWindow : public QWidget, protected DataShare
class StatWindow : public QWidget, protected DataShare
其中,“, protected DataShare” 为新增代码。
原理:
在类中定义一个静态成员当然可以实现数据共享,但C++的静态成员必须在类外进行赋值,并且所有类都可以直接通过类名进行访问(无法作为私有成员。破坏了类对成员的封装保护,并且必须以“DataShare::grade”这样的方式进行访问,非常不优雅)。思来想去,终于找到了一种非常巧妙的方法(见代码):
实际的数据存放于DataShare类的sharedData成员函数中的静态变量static Grade dataShare。这样做可以绕过静态成员必须在类外初始化的缺点。
当执行DataShare::DataShare()构造函数时,会执行下面的语句:this->sharedData() = Grade(); 新创建的Grade对象被赋值给了sharedData函数(什么?函数还能被赋值?)。能被赋值的原因是sharedData被定义为返回值是引用的函数。这样,this->sharedData() = Grade()相当于sharedData函数的静态变量dataShare被赋值。因为希望共享的数据是grade,所以sharedData被定义为私有函数,防止子类具有访问权。
我们再来看Grade& grade = sharedData(); grade被定义为保护类型的成员变量,即保证了数据的封装性,又能继承给子类使用。实际使用时,可以直接赋值给grade或者调用grade。原因:grade成员变量是sharedData静态函数返回值的引用,而sharedData返回值又是sharedData函数的静态变量dataShare的引用。这样,当我们直接访问grade成员变量的时候,可以直接视作为类的一个静态函数中的静态变量的引用,而我们都知道函数的静态变量是存放在静态存储区的。又因为函数是静态函数,变量是静态变量,故实际数据只会在整个程序中存储且只存储一份。这样,无论有多少个类继承于DataShare,都只会共享一份grade(数据),并且由于继承了保护成员Grade& grade = sharedData(),又都可以在自己的类中直接使用grade成员变量。通过这样的方法,就能实现不同类之间的数据精确共享了。
至此,这篇关于C++如何实现多个类之间数据共享的教程就结束了。如果大家仍有问题,欢迎在评论区留言或者小窗私信~~