文章目录
二十二、特殊类的设计
1. 请设计一个类,不能被拷贝
拷贝只会放生在两个场景中:拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。
C++98:
#include <iostream>
using namespace std;
class myClass
{
// 私有化
myClass(const myClass& myc);
myClass& operator=(const myClass& myc);
public:
myClass()
{}
~myClass()
{}
private:
int _a;
};
int main()
{
myClass my1;
myClass my2(my1);
my2 = my1;
return 0;
}
C++11扩展delete的用法,delete除了释放new申请的资源外,如果在默认成员函数后跟上=delete,表示让编译器删除掉该默认成员函数。
C++11:
#include <iostream>
using namespace std;
class myClass
{
public:
myClass()
{}
~myClass()
{}
myClass(const myClass& myc) = delete;
myClass& operator=(const myClass& myc) = delete;
private:
int _a;
};
int main()
{
myClass my1;
myClass my2(my1);
my2 = my1;
return 0;
}
2. 请设计一个类,只能在堆上创建对象
实现方式:将类的构造函数私有,拷贝构造声明成私有(或delete)。防止别人调用拷贝在栈上生成对象。再提供一个静态的成员函数,在该静态成员函数中完成堆对象的创建。
#include <iostream>
using namespace std;
class HeapOnly
{
public:
static HeapOnly* CreateObject()
{
return new HeapOnly;
}
HeapOnly(const HeapOnly&) = delete;
private:
HeapOnly()
{}
//HeapOnly(const HeapOnly&);
};
int main()
{
HeapOnly h;
HeapOnly* hp = HeapOnly::CreateObject();
return 0;
}
3. 请设计一个类,只能在栈上创建对象
同上将构造函数私有化(或delete),然后设计静态方法创建对象返回即可。为了防止使用new来创建堆对象,我们需要手动在类内声明operator new函数,并将其delete掉。
#include <iostream>
using namespace std;
class StackOnly
{
public:
static StackOnly CreateObj()
{
return StackOnly();
}
void* operator new(size_t size) = delete;
void operator delete(void* p) = delete;
private:
StackOnly()
:_a(0)
{}
private:
int _a;
};
int main()
{
StackOnly s;
StackOnly* sp = new StackOnly;
StackOnly s2 = StackOnly::CreateObj();
return 0;
}
4. 请设计一个类,不能被继承
①将构造函数私有化,派生类中调不到基类的构造函数。则无法继承。
②C++11新关键字 final 修饰的类不能再被继承。
#include <iostream>
using namespace std;
// C++98
class NonInherit
{
public:
private:
NonInherit()
{}
};
class A : public NonInherit
{
public:
A()
{}
private:
};
// C++11
class B final
{
public:
B()
{}
private:
};
class C : public B
{
};
int main()
{
return 0;
}
5. 请设计一个类,只能创建一个对象(单例模式)
一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。
一般来说,单例模式有两种实现方式:①饿汉模式 ②懒汉模式
饿汉模式:不管你将来用不用,程序启动时就创建一个唯一的实例对象。
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton* GetInstance()
{
return &m_instance;
}
Singleton(Singleton const&) = delete;
Singleton& operator=(Singleton const&) = delete;
private:
// 构造函数私有
Singleton()
{}
// 静态对象--存在静态区,不在对象内
static Singleton m_instance;
};
// 程序开始时就完成对单例对象的初始化
Singleton Singleton::m_instance;
由于饿汉模式在程序进入主函数前就需要把对象创建出来,如果单例模式太多,或者这个对象太大,则会拖慢程序的启动,对性能要求较高。或者要求对对象的创建顺序有要求,都不适合饿汉模式。
懒汉模式:第一次使用实例对象时,才创建对象。
我们需要判断是否是第一次使用实例,如果是第一次使用实例才创建对象,否则返回原本就存在的对象。
#include <iostream>
using namespace std;
class Singleton
{
public:
// 创建对象
static Singleton* GetInstance()
{
// 只有第一次调用时,才创建对象
if (_psint == nullptr)
{
// C++98
_psint = new Singleton;
return _psint
// C++11
// static Singleton _psint;
// return &_psint;
}
return _psint;
}
Singleton(Singleton const&) = delete;
Singleton& operator=(Singleton const&) = delete;
private:
Singleton()
{}
// 对象指针
static Singleton* _psint;
};
// 初始化
Singleton* Singleton::_psint = nullptr;