C++、Java与Python静态变量的定义与引用对比(内存中转存储)

发布于 2021-03-11  590 次阅读


一、应用场景

二、对比

(一)C++

C++以CMake项目为实例进行说明,定义一个Database类,里面包含一个静态变量PI,设计目标为:类实例化的不同对象对其进行修改,能够在内存中保存。
比如从磁盘中读取文本后,通过实例化Database对象存储到PI中;在其他地方实例化新的Database对象后,能够读取的PI为刚刚存储的文本数据。

Database头文件如下:

#pragma once
#ifndef _DATABASE_H

#define _DATABASE_H

#include <iostream>
using namespace std;

class Database
{
private:
    static double PI;
public:
    Database();
    ~Database();
    void setPI(double newValue);
    double getPI();
};

#endif

,cpp源代码文件:


#include "Database.h"

//没有这条,静态变量不起作用!
double Database::PI = 2.0000;

Database::Database()
{
    cout << "- 实例化的新对象:";
}

Database::~Database(){}

void Database::setPI(double newValue)
{
    this->PI = newValue;
}

double Database::getPI()
{
    return this->PI;
}

主函数(项目)头文件:

// CMakeLearnCplus.h: 标准系统包含文件的包含文件
// 或项目特定的包含文件。
#include <iostream>

// TODO: 在此处引用程序需要的其他标头。
//引入Database头文件
#include "Database.h"

主函数源代码:

// CMakeLearnCplus.cpp: 定义应用程序的入口点。
//

#include "CMakeLearnCplus.h"
using namespace std;

int main()
{

    Database databse1;

    databse1.setPI(3.141592600);
    cout <<"1号对象设置的值:"<< databse1.getPI() << endl;
    Database database2;
    database2.setPI(2.3645);
    cout << "2号对象设置的值:" << database2.getPI() << endl;
    cout <<"2号对象设置值后,1号对象重新获取值:"<< databse1.getPI() << endl;
    cout <<"3号对象未设置任何值直接获取:"<< Database().getPI() << endl;
    cin.get();
    return 0;
}

执行结果如下:

file

可以发现,总共实例化了三个类对象,在不同的对象中,静态变量PI的值被修改且保存上次次修改的结果。

(二)Java

Java的定义方式与C++大致相同,定义static静态变量后通过其他函数进行查、删、改等操作。

    public static double PI = 3.14159256;

没有很大的区别,不做多赘述。

(三)Python

Python是动态语言,对于数据类型,并没有一开始就定好数据类型,也就没有专门用来定义静态变量的保留字。

故而Python的静态数据引用,可以通过如下方式:

3.1 类名.变量

  • 建立静态类
  • 定义系列变量
  • 通过类名(注意,不是实例化对象)执行点运算实现静态数据存储、引用、修改

以本人开发的PyQt5前端框架为例:

class Database(object):
    """
    # 模型相关配置,载入方式为:类名.属性 Ex: Database.modelPath
    # 上述操作需要预先对Database进行初始化,由软件启动时完成
    # 如需测试,载入方式为:实例化类.属性 ,Ex: Database().loadJsonConfig,Database.modelPath
    """
    jsonPath = "./source/para_json/config.json"
    modelPath = None
    default_modelPath = None
    font = None

如需要在系统全局设定模型路径:modelPath = None,在其他.py文件内,只需要导入Database类后:

Database.modelPath = "./workspace/tes.model_3"

3.2 装饰器实现

或是通过@property装饰器实现,此方式较为流行。

class Database(object):
    """
    _modelPath = None # 不直接操作变量

    @property
    def modelPath(self):
        return Database._modelPath

    @modelPath.setter
    def modelPath(self, modelPath):
        Database._modelPath = modelPath
# 两个函数保持同名

其使用方法为:

tesDa = Database()
# 设置
tesDa.modelPath = "./workspace/tes.model_3"
#读取
path = tesDa.modelPath

3.3 推荐用法

但在本人设计的PyQt5项目中,广泛采用第一种方式,原因有以下几点:

1.创建、引用方式较为便利,不需要很多代码,实现起来较为简单;
2.通过类名引用的方式,亦不会引发混乱,与同类实例化后的对象属性数据可以共享(共享静态数据);

但要特别注意,共享也就意味着,类实例化后的属性可能不是设计时的数据。

三、总结