• 单例模式、工厂模式 c++关键字 static


    static 关键字的作用:

    主要作用在于 控制变量或函数的作用域生命周期以及它们如何被不同部分的程序访问,从而帮助程序员管理内存、避免命名冲突,并实现特定的设计模式(如单例模式)。

    • 1. 静态局部变量:当在一个函数内部声明一个静态局部变量(如下面单例模式示例中的static BoxFactory boxFactory;),这个变量的生命周期将延伸到包含它的函数结束之后。这样的静态局部变量在程序运行期间只会被初始化一次,即使函数被多次调用。它保留了上一次函数调用结束时的值。

    • 2.静态全局变量:在文件作用域声明的静态变量(即在函数外部,但用static修饰),其作用范围限制在定义它的源文件内,即它是“内部链接”的。这意味着其他源文件中的代码不能直接访问这个变量,有助于减少命名冲突并封装数据。

    • 3.静态成员变量:在类声明中使用static声明的成员变量不属于类的任何特定实例,而是属于整个类。所有类实例共享同一个静态成员变量的副本。静态成员变量必须在类定义之外初始化。静态成员可以通过类名直接访问,无需实例化对象

    • 4.静态成员函数:静态成员函数也是类的一部分,但不与类的任何特定实例关联。它们不能访问非静态成员变量(因为非静态成员变量是特定于实例的),但可以访问静态成员变量和其他静态成员函数。静态成员函数同样通过类名直接调用,无需实例化对象

    • 5.静态外部变量声明:在头文件中使用extern和static声明变量,可以让多个源文件共享同一变量的声明,但每个使用该声明的源文件需要有一个独立的定义(没有static),以避免多重定义错误。这种方式主要用于跨文件共享常量或全局数据。

    static 关键字示例:

    1.静态局部变量

    下面代码中有两个函数fun1和fun2,其中fun2中的局部变量b用static关键字修饰成静态局部变量,那么变量b不是在栈区上创建的,而是在静态区上创建的。在静态区上创建的变量,生命周期是全局的,也就是说,静态局部变量的生命周期和程序的生命周期相同
    我们分别运行五次fun1()和fun2(),会发现b只会被创建一次,后面执行fun2()函数时由于存储在静态区没有被销毁,所以还是使用的已经存在的b并不会重新创建,理解这一点对单例模式中全局唯一一次类的实例化很关键

    void fun1() {
    	int a = 0;
    	a++;
    	printf(" a = %d   | ", a);
    }
    
    void fun2() {
    	static int b = 0;
    	b++;
    	printf(" b = %d   | ", b);
    }
    
    void main()
    {
    	for (size_t i = 0; i < 10; i++)
    	{
    		if (i < 5) fun1();
    		else fun2();
    	}
    }
    

    在这里插入图片描述

    2.静态全局变量

    静态全局变量的例子就不举例了,很多理解,被static修饰的全局变量只能在本cpp文件中访问。

    3.静态成员函数,静态成员变量

    设计模式中的工厂模式+单例模式很好解释静态成员函数的用法:
    下面的代码块有四个类:
    我们可以通过工厂类可以实例化圆形 和正方形,但每次用工厂类的时候,我们不需要每次都实例化一个工厂,因此工厂类就用到了单例模式,使工厂在整个系统的生命周期唯一,避免多次创建。
    在这里插入图片描述
    此外阅读时注意工厂类中getInstance()使用static 修饰,

    	static ShapeFactory& getInstance() //静态成员函数
    	{
    		static ShapeFactory instance;  //静态成员变量
    		return instance;
    	}
    
    • 确保唯一性:通过将getInstance方法声明为静态成员函数,可以不依赖于类的任何实例直接访问。这使得无论何时何地调用getInstance,都只会返回同一个ShapeFactory实例,保证了全局唯一性。
    • 全局访问:静态方法可以在不创建类实例的情况下被调用,因此可以在程序的任何地方访问工厂类的单例,便于统一管理和协调对象的创建过程。
      因此在调用时还可以写成:
    int main()
    {
    	
    	auto circle = ShapeFactory::getInstance().createShape("Circle");
    	if (circle)
    	{
    		circle->draw();
    	}
    
    	auto square = ShapeFactory::getInstance().createShape("Circle");
    	if (square)
    	{
    		square->draw();
    	}
    
    	return 0;
    }
    
    #include 
    #include 
    #include 
    using namespace std;
    
    
    // 抽象形状类
    class Shape
    {
    public:
    	virtual ~Shape() {}
    	virtual void draw() const = 0;
    };
    
    // 圆形类
    class Circle : public Shape
    {
    public:
    	void draw() const override
    	{
    		std::cout << "Drawing Circle" << std::endl;
    	}
    };
    
    // 正方形类
    class Square : public Shape
    {
    public:
    	void draw() const override
    	{
    		std::cout << "Drawing Square" << std::endl;
    	}
    };
    
    // 形状工厂类 - 单例模式
    class ShapeFactory
    {
    public:
    	static ShapeFactory& getInstance()
    	{
    		static ShapeFactory instance;
    		return instance;
    	}
    
    	Shape* createShape(const std::string& shapeType)
    	{
    		if (shapeType == "Circle")
    
    		{
    			Circle* pCircle = new Circle();
    			return pCircle;
    		}
    		else if (shapeType == "Square")
    		{
    			Square* pSquare = new Square();
    			return pSquare;
    		}
    		else
    		{
    			return NULL;
    		}
    	}
    
    
    private:
    	ShapeFactory() = default;								// 私有构造函数
    	ShapeFactory(const ShapeFactory&) = delete;			// 禁止拷贝构造
    	ShapeFactory& operator=(const ShapeFactory&) = delete; // 禁止赋值操作
    };
    
    int main()
    {
    	ShapeFactory& factory = ShapeFactory::getInstance(); // 获取工厂单例
    	auto circle = factory.createShape("Circle");
    	if (circle)
    	{
    		circle->draw();
    	}
    
    	auto square = factory.createShape("Square");
    	if (square)
    	{
    		square->draw();
    	}
    
    	return 0;
    }
    
    

    我们可以通过一下代码来验证工厂类是否在全局中只创建了一次

    // 形状工厂类 - 单例模式
    class ShapeFactory
    {
    public:
    	static ShapeFactory& getInstance()
    	{
    		static ShapeFactory instance;
    		return instance;
    	}
    
    	Shape* createShape(const std::string& shapeType)
    	{
    		if (shapeType == "Circle")
    
    		{
    			Circle* pCircle = new Circle();
    			return pCircle;
    		}
    		else if (shapeType == "Square")
    		{
    			Square* pSquare = new Square();
    			return pSquare;
    		}
    		else
    		{
    			return NULL;
    		}
    	}
    
    
    private:
    	ShapeFactory();// 私有构造函数
    	~ShapeFactory();
    	ShapeFactory(const ShapeFactory&) = delete;			// 禁止拷贝构造
    	ShapeFactory& operator=(const ShapeFactory&) = delete; // 禁止赋值操作
    };
    
    ShapeFactory::ShapeFactory() {
    	std::cout << "工厂类构造函数" << std::endl;
    }
    
    ShapeFactory::~ShapeFactory() {
    	std::cout << "工厂析构函数" << std::endl;
    }
    int main()
    {
    	for (int i = 0; i < 5; i++) {
    		ShapeFactory& factory = ShapeFactory::getInstance(); // 获取工厂单例
    		std::cout << "i = " << i << std::endl;
    	}
    	return 0;
    }
    

    在这里插入图片描述

  • 相关阅读:
    关于Allegro17.4 3d模型大小不匹配问题解决
    MySQL数据库之索引
    2022.8.4 模拟赛
    【大数据技术】hive 跑mapreduce报错
    【JavaWeb】-- Servlet优化(dispatcherServlet)
    嵌入式STM32 单片机 GPIO 的工作原理详解
    嵌套字典遍历取值,并得到值的键路径
    基于STM32设计的智能货架(华为云IOT)(225)
    POI生成Word水印watermark(兼容WPS)的终极解决方案
    痞子衡嵌入式:IAR环境下无法直接下载调试i.MXRT分散链接工程的解决方案(宏文件.mac+双Flashloader)
  • 原文地址:https://blog.csdn.net/qq_42573052/article/details/139504190