特殊类设计

1. 请设计一个 不能拷贝 的类

C++ 98:

template<class T>
class Copy_Ban
{
private:
	Copy_Ban(Copy_Ban<T>& cb);
	Copy_Ban<T>& operator=(Copy_Ban<T>& cb);
};

拷贝构造赋值重载 只声明不定义且私有化

C++ 11:

template<class T>
class Copy_Ban
{
public:
	Copy_Ban(Copy_Ban<T>& cb) = delete;
	Copy_Ban<T>& operator=(Copy_Ban<T>& cb) = delete;
};

error C2280: “Copy_Ban::Copy_Ban(Copy_Ban &)”: 尝试引用已删除的函数

2. 请设计一个 只能在堆上创建对象 的类

核心步骤只有 3 条:

  • 将构造私有化
  • 通过特定接口创建对象
  • 将 拷贝构造 和 赋值重载 封死
class HeapOnly
{
public:
    // 2. 通过特定接口创建对象
	template<class... Args>
	static HeapOnly* GetInstance(Args... args) // static 非静态成员函数(不需要使用 this)
	{
		return new HeapOnly(args...);
	}
	
    // 3. 将 拷贝构造 和 赋值重载 封死
	HeapOnly(const HeapOnly&) = delete;
	HeapOnly& operator=(const HeapOnly&) = delete;
    
    // ...
private:
    // 1. 将构造函数私有化
	HeapOnly(int x)
		:_data(x)
	{}
	HeapOnly() {}

	int _data;
	vector<int> _v;
};

创建对象:

	HeapOnly* ho = HeapOnly::GetInstance();
	// 可以通过 ho 调用类内部的各种函数
3. 请设计一个 只能在栈上创建对象 的类
  • 将构造私有化
  • 通过特定接口创建对象
  • 将 operator new (operator delete)封死
class StackOnly
{
public:
	template<class... Args>
	static StackOnly GetInstance(Args... args)
	{
		return  StackOnly(args...);
	}
	
    // 固定写法
	void* operator new(size_t) = delete;
	void operator delete(void*) = delete;
private:
	StackOnly(int x)
		:_data(x)
	{}

	StackOnly()
	{}

	int _data;
	vector<int> _v;
};

创建对象:

	StackOnly so = StackOnly::GetInstance();
何时需要删除 operator= ?
  1. 你的类被设计成不可复制的(既不能被拷贝构造,也不能被赋值)。
  2. 你的类包含了一些不允许复制的成员,因为这些成员类型可能自己就禁止了拷贝和赋值。
4. 请设计一个 不能被继承 的类

C++ 98:

将构造函数私有化派生类(子类)无法调用基类(父类)的构造函数,则无法被继承。

struct A
{
private:
    A() {}
};

struct B : public A
{
public:
    B() {} // error C2248: “A::A”: 无法访问 private 成员(在“A”类中声明)
};

C++ 11:

使用关键词 final 修饰类。

struct A final
{
public:
	A() {}
};

struct B : public A // error C3246: “B”: 无法从“A”继承,因为它已被声明为“final”
{
public:
	B() {}
};
5. 请设计 只能创建一个对象 的类(单例模式)(不加锁)

单例模式: 一个类只能创建一个对象,并提供一个全局访问点来获取该实例。

  • 饿汉模式:单例对象在类加载时就会被创建。 单例对象的生命周期与程序的生命周期相同,从程序开始运行到程序运行结束,单例对象始终存在。

​ 缺点:1. 单例对象一旦被创建,就会一直占用内存。

​ 2. 如果单例对象创建时需要执行耗时的操作,会影响程序的启动速度 —— 单例对象在 main 函数开始之前被创建。

namespace hunger
{
	class Singleton
	{
	public:
        // 提供全局访问点来获取实例
		static Singleton* GetInstance()
		{
			return &_sint;
		}
		
        // 删除拷贝构造和赋值运算符重载,防止复制
		Singleton(const Singleton&) = delete;
		Singleton& operator=(const Singleton&) = delete;

	private:
        // 私有化构造函数
		Singleton() {}
		
        // 静态成员变量保存实例
		static Singleton _sint;
	};
	// 初始化静态成员变量
	Singleton Singleton::_sint;
}
  • 懒汉模式:单例对象在第一次被请求时才创建,节省资源。

​ 缺点: 1. 在多线程环境中,如果没有正确的线程同步机制,可能会创建多个实例,破坏单例特性

(未加锁版本)

namespace lazy
{
	class Singleton
	{
	public:
		static Singleton* GetInstance()
		{
            // 第一次被请求时,创建对象
			if (_sint == nullptr)
			{
				_sint = new Singleton;
			}
			return _sint;
		}

		static void DestroyInstance()
		{
			if (_sint)
			{
				delete _sint;
				_sint = nullptr;
			}
		}
		// 删除拷贝构造和赋值运算符重载,防止复制
		Singleton(const Singleton&) = delete;
		Singleton& operator=(const Singleton&) = delete;

	private:
        // 私有化构造函数和析构函数
		~Singleton()
		{
            cout << "~Singleton()" < endl;
		}

		Singleton() {
            cout << "Singleton()" << endl;
        }

		static Singleton* _sint;
	};
	// 初始化静态成员单例对象
	Singleton* Singleton::_sint = nullptr;
}

上面这段代码有一个小缺点:需要手动调用 lazy::Singleton::DestroyInstance(); 完成单例对象的释放。

优化一下:

// version 1
namespace lazy
{
    class Singleton
    {
        // ,,,
    };
    
    struct GC
    {
        GC() {}
        ~GC() { Singleton::DestroyInstance(); }
    };
    GC gc;
}

//  version 2
namespace lazy
{
    class Singleton
    {
        // ,,,
    private:
        // 设计成内部私有类,用户就无法手动调用 GC 的析构函数,释放单例对象
        struct GC
        {
            GC() {}
            ~GC() { Singleton::DestroyInstance(); }
        };
        GC gc;
    };
}

相关推荐

  1. C++特殊设计

    2024-07-17 09:38:06       48 阅读
  2. 特殊设计

    2024-07-17 09:38:06       53 阅读
  3. 【C++】特殊设计

    2024-07-17 09:38:06       44 阅读
  4. C++特殊设计

    2024-07-17 09:38:06       42 阅读
  5. 特殊设计

    2024-07-17 09:38:06       50 阅读
  6. C++特殊设计

    2024-07-17 09:38:06       43 阅读
  7. c++特殊设计

    2024-07-17 09:38:06       37 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-17 09:38:06       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-17 09:38:06       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-17 09:38:06       58 阅读
  4. Python语言-面向对象

    2024-07-17 09:38:06       69 阅读

热门阅读

  1. Spring MVC-11

    2024-07-17 09:38:06       23 阅读
  2. Linux 驱动开发 举例

    2024-07-17 09:38:06       18 阅读
  3. ES6及ESNext规范

    2024-07-17 09:38:06       25 阅读
  4. Mysql---基础篇

    2024-07-17 09:38:06       27 阅读
  5. 前端数据加密方式

    2024-07-17 09:38:06       24 阅读
  6. Oracle(2)Oracle数据库的主要组件有哪些?

    2024-07-17 09:38:06       22 阅读
  7. 大语言模型 API

    2024-07-17 09:38:06       23 阅读
  8. 通过手机控制家用电器的一个程序的设计(一)

    2024-07-17 09:38:06       25 阅读
  9. 深度学习中的正则化技术 - 稀疏表示篇

    2024-07-17 09:38:06       27 阅读
  10. CPTAC蛋白数据库在线蛋白分析(癌与癌旁)

    2024-07-17 09:38:06       23 阅读