Qt使用单例模式读取xml文件

这篇具有很好参考价值的文章主要介绍了Qt使用单例模式读取xml文件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、单例模式介绍

1、什么是单例模式

单例模式是指在整个系统生命周期内,保证一个类只能产生一个实例,确保该类的唯一性。

2、为什么使用单例模式

1、节省资源。一个类只有一个实例,不存在多份实例,节省资源。
2、方便控制。在一些操作公共资源的场景时,避免了多个对象引起的复杂操作。

3、什么情况下使用单例模式

在程序中多次使用同一个对象且作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象。

4、使用单例模式需要注意哪些问题

线程安全
  • 什么是线程安全

在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。

  • 如何保证线程安全

1、给共享的资源加把锁,保证每个资源变量每时每刻至多被一个线程占用。
2、让线程也拥有资源,不用去共享进程中的资源。如:使用threadlocal可以为每个线程维护一个私有的本地变量。

5、单例模式的类型

  • 懒汉式

系统运行中,实例并不存在,只有当需要使用该实例时,才会去创建并使用实例。这种方式要考虑线程安全。

  • 饿汉式

系统一运行,就初始化创建实例,当需要时,直接调用即可。这种方式本身就线程安全,没有多线程的线程安全问题。

6、单例类的特点

  • 构造函数和析构函数为私有类型,目的是禁止外部构造和析构。
  • 拷贝构造函数和赋值构造函数是私有类型,目的是禁止外部拷贝和赋值,确保实例的唯一性。
  • 类中有一个获取实例的静态方法,可以全局访问。

2、单例模式的实现

2.1懒汉式

加锁的懒汉式单例(线程安全)
头文件:

///  加锁的懒汉式实现  //

class SingleInstance
{

public:
    // 获取单实例对象
    static SingleInstance *GetInstance();

    //释放单实例,进程退出时调用
    static void deleteInstance();

	//返回所有的IP
	QVariantList getIP(){return m_ips;}
	
	//获取XML文件
	bool initalize();
	
    // 打印实例地址
    void Print();

private:
    // 将其构造和析构成为私有的, 禁止外部构造和析构
    SingleInstance();
    ~SingleInstance();

    // 将其拷贝构造和赋值构造成为私有函数, 禁止外部拷贝和赋值
    SingleInstance(const SingleInstance &signal);
    const SingleInstance &operator=(const SingleInstance &signal);

    //解析xml中的内容
    void parseIP(const QDomNode &root);

private:
    // 唯一单实例对象指针
    static SingleInstance *m_SingleInstance;
    static std::mutex m_Mutex;
    //存储IP
    QVariantList m_ips;
};

源文件:

//初始化静态成员变量
SingleInstance *SingleInstance::m_SingleInstance = nullptr;
std::mutex SingleInstance::m_Mutex;

// 注意:不能返回指针的引用,否则存在外部被修改的风险!
SingleInstance * SingleInstance::GetInstance()
{

    //  这里使用了两个 if 判断语句的技术称为双检锁;好处是,只有判断指针为空的时候才加锁,
    //  避免每次调用 GetInstance的方法都加锁,锁的开销毕竟还是有点大的。
    if (m_SingleInstance == nullptr) 
    {
        std::unique_lock<std::mutex> lock(m_Mutex); // 加锁
        if (m_SingleInstance == nullptr)
        {
            volatile auto temp = new (std::nothrow) SingleInstance();
            m_SingleInstance = temp;
        }
    }

    return m_SingleInstance;
}

void SingleInstance::deleteInstance()
{
    std::unique_lock<std::mutex> lock(m_Mutex); // 加锁
    if (m_SingleInstance)
    {
        delete m_SingleInstance;
        m_SingleInstance = nullptr;
    }
}

bool SingleInstance::initalize()
{
	QString path("目录");
	QFile file(path);
	if(file.exists())
	{
		if(file.open(QIODevice::ReadOnly | QIODevice::Truncate))
		{
			QString error;
			QDomDocument document;
			document.setContent(&file, &error);
			file.close();
			if(document.isNull())
			{
				qDebug() << QString("文件格式异常:1%").arg(error);
				return false;
			}
			QDomNode root = document.firstChild();
			parseIP(root);
		}else{
			qDebug() << QString("%1:文件不存在,:2%").arg(path).arg(file.errorString());
		}
	}else{
		qDebug() QString("%1:文件不存在!").arg(path);
		return false;
	}
	return !m_ips.isEmpty();
}

void SingleInstance::Print()
{
	std::cout << "我的实例内存地址是:" << this << std::endl;
}

SingleInstance::SingleInstance()
{
    std::cout << "构造函数" << std::endl;
}

SingleInstance::~SingleInstance()
{
    std::cout << "析构函数" << std::endl;
    deleteInstance();
}

void SingleInstance::parseIP(const QDomNode &root)
{
	QDomNode startnode = root.nextSibling();
	QDomNode node = startnode.firstChild();
	while(!node.isNull())
	{
		QVariantMap ips;
		ips.clear();
		QDomElement element = node.toElement();
		ips.insert("ip", element.attribute("ip"));
		ips.insert("port", element.attribute("port"));
		ips.insert("multiip", element.attribute("multiip"));
	}
	
}

main.cpp

if(Singleton::GetInstance()->initalize())
{
...
}

2.2饿汉式

头文件

// 饿汉实现 /

class Singleton
{
public:
    // 获取单实例
    static Singleton* GetInstance();

    // 释放单实例,进程退出时调用
    static void deleteInstance();
	
	//返回所有的IP
	QVariantList getIP(){return m_ips;}
	
	//获取XML文件
	bool initalize();
    
    // 打印实例地址
    void Print();

private:
    // 将其构造和析构成为私有的, 禁止外部构造和析构
    Singleton();
    ~Singleton();

    // 将其拷贝构造和赋值构造成为私有函数, 禁止外部拷贝和赋值
    Singleton(const Singleton &signal);
    const Singleton &operator=(const Singleton &signal);
    
    //解析xml中的内容
    void parseIP(const QDomNode &root);

private:
    // 唯一单实例对象指针
    static Singleton *g_pSingleton;
    
    //存储IP
    QVariantList m_ips;
};

源文件:

// 代码一运行就初始化创建实例 ,本身就线程安全
Singleton* Singleton::g_pSingleton = new (std::nothrow) Singleton();

Singleton* Singleton::GetInstance()
{
    return g_pSingleton;
}

void Singleton::deleteInstance()
{
    if (g_pSingleton)
    {
        delete g_pSingleton;
        g_pSingleton = nullptr;
    }
}

bool SingleInstance::initalize()
{
	QString path("目录");
	QFile file(path);
	if(file.exists())
	{
		if(file.open(QIODevice::ReadOnly | QIODevice::Truncate))
		{
			QString error;
			QDomDocument document;
			document.setContent(&file, &error);
			file.close();
			if(document.isNull())
			{
				qDebug() << QString("文件格式异常:1%").arg(error);
				return false;
			}
			QDomNode root = document.firstChild();
			parseIP(root);
		}else{
			qDebug() << QString("%1:文件不存在,:2%").arg(path).arg(file.errorString());
		}
	}else{
		qDebug() QString("%1:文件不存在!").arg(path);
		return false;
	}
	return !m_ips.isEmpty();
}

void Singleton::Print()
{
    std::cout << "我的实例内存地址是:" << this << std::endl;
}

Singleton::Singleton()
{
    std::cout << "构造函数" << std::endl;
}

Singleton::~Singleton()
{
    std::cout << "析构函数" << std::endl;
    deleteInstance();
}

void SingleInstance::parseIP(const QDomNode &root)
{
	QDomNode startnode = root.nextSibling();
	QDomNode node = startnode.firstChild();
	while(!node.isNull())
	{
		QVariantMap ips;
		ips.clear();
		QDomElement element = node.toElement();
		ips.insert("ip", element.attribute("ip"));
		ips.insert("port", element.attribute("port"));
		ips.insert("multiip", element.attribute("multiip"));
	}
	
}


main.cpp

if(Singleton::GetInstance()->initalize())
{
...
}

xml说明文章来源地址https://www.toymoban.com/news/detail-830741.html

<?xml version="1.0" encoding="utf-8"?>XML声明是XML文档的第一句
<ips>
<ip ip="xxx" port="xxx" multiip="xxx"/>
</ips>

到了这里,关于Qt使用单例模式读取xml文件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • QT解析xml文件

    mainwindow.cpp  mainwindow.h

    2024年02月14日
    浏览(34)
  • qt读写xml文件

    Qt使用XML模块,在.pro文件中添加 QT += xml Qt 提供了三种读 写  XML 文档的方法: QXmlStreamReader / QXmlStreamWriter: 一种快速的基于流的方式访问良格式 XML 文档 , 特别适合于实现一次解析器(所谓“一次解析器”,可以理解成我们只需读取文档一次,然后像一个遍历器从头到尾一

    2024年02月11日
    浏览(38)
  • 利用Qt输出XML文件

    使用Qt输出xml文件 写入生成的xml文件如下:

    2024年02月02日
    浏览(47)
  • Qt XML文件解析 QDomDocument

    QtXml模块提供了一个读写XML文件的流,解析方法包含DOM和SAX,两者的区别是什么呢? DOM(Document Object Model):将XML文件保存为树的形式,操作简单,便于访问。 SAX(Simple API for XML):接近于底层,速度较快,但不便于访问。 如果要使用XML时,.pro文件中添加:  使用时添加文件

    2024年02月10日
    浏览(47)
  • Qt XML文件读、写、修改

    1.1 使用的库 1.2 主体语句 头部创建: 内容创建: 1.3 详细例子说明 .cpp文件

    2024年02月11日
    浏览(39)
  • Qt中XML文件创建及解析

    QT的配置文件中添加xml选项: 头文件:#include QXmlStreamWriter 写入的文件如图:   头文件:#include QXmlStreamReader  解析其中的Hobby模块: 输出结果:  

    2024年02月11日
    浏览(33)
  • Qt读写ini配置文件(QSettings)、XML

    1、ini相关的 总结:Qt读写ini配置文件(QSettings) - 布丁Plus - 博客园 (cnblogs.com) Qt读写ini文件(含源码+注释)_qt ini文件读写_lw向北.的博客-CSDN博客 2、XML相关的 Qt读写XML文件(含源码+注释)_qt写xml_lw向北.的博客-CSDN博客

    2024年02月11日
    浏览(47)
  • QT单例的简单使用

    单例的.h文件 单例的.cpp文件 使用单例的.cpp代码

    2024年02月16日
    浏览(30)
  • Qt 实例3 读取txt文件

    通过简单实例小程序,实现txt文件读取展示。 1、创建工程并进行界面设计。创建基于QWidget基类的Qt界面应用程序,并在主界面添加相关控件如下: 界面控件依次为:QLabel、QLineEdit、QPushButton、QTextEdit。 2、创建并绑定槽函数 .h头文件创建槽函数: .cpp源文件构造函数内绑定槽

    2024年02月11日
    浏览(40)
  • Qt6.5示例:QDomDocument类解析XML文档和文件

    QDomDocument类是用于处理XML文档的一个类。QDomDocument提供了对XML文档数据访问的一系列功能,主要功能包括如下: 解析XML文档:QDomDocument可以将XML文档解析为树形结构,每个节点都是一个QDomNode对象,可以通过QDomNode对象的方法来访问和修改节点属性和内容。 创建XML元素和文本

    2024年01月20日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包