【C++】特殊类设计
特殊类设计
- 1.设计类:不能被拷贝
- 2.设计类:不能被继承
- 3.设计类:只能在堆上创建对象
- 4.设计类:只能在栈上创建对象
- 5.设计类:只能创建一个对象(单例模式)
本节重点:
- 掌握特殊类的设计方式
1.设计类:不能被拷贝
// C++98私有化
class Copy
{
private:
Copy(const Copy&);
Copy& operator=(const Copy&);
};
// C++11关键字delete
class Copy
{
public:
Copy(const Copy&) = delete;
Copy& operator=(const Copy&) = delete;
};
2.设计类:不能被继承
// C++98中构造函数私有化, 派生类无法调用基类的构造函数, 无法继承
class NoInherit
{
public:
static NoInherit GetInstance()
{
return NoInherit();
}
private:
NoInherit()
{}
};
// C++11关键字fianl
class NoInherit final
{
// ...
};
3.设计类:只能在堆上创建对象
class HeapOnly
{
public:
static HeapOnly* CreateObj()
{
return new HeapOnly();
}
// 禁用: 拷贝构造和拷贝赋值
HeapOnly(const HeapOnly&) = delete;
HeapOnly& operator=(const HeapOnly&) = delete;
private:
// 默认构造私有化
HeapOnly()
{}
};
int main()
{
// HeapOnly obj1;
// static HeapOnly obj2;
// HeapOnly *obj3 = new HeapOnly();
HeapOnly* obj4 = HeapOnly::CreateObj();
// HeapOnly obj5(*obj4);
// HeapOnly obj6 = *obj4;
delete obj4;
return 0;
}
class HeapOnly
{
public:
void Delete()
{
delete this;
}
private:
// 析构函数私有化
~HeapOnly()
{}
};
int main()
{
// 程序结束调用析构函数, 由于私有化, 无法创建对象
// HeapOnly obj1;
// static HeapOnly obj2;
// 可以在堆上创建对象, 但是调用delete存在问题(delete: 先调用析构函数, 再释放空间)
// HeapOnly* obj3 = new HeapOnly();
// delete obj3;
HeapOnly *obj4 = new HeapOnly();
obj4->Delete();
return 0;
}
4.设计类:只能在栈上创建对象
class StackOnly
{
public:
static StackOnly CreateObj()
{
return StackOnly();
}
void* operator new(size_t) = delete;
void operator delete(void*) = delete;
private:
StackOnly()
{}
};
int main()
{
// StackOnly obj1;
// static StackOnly obj2;
// StackOnly* obj3 = new StackOnly();
// 传值返回需要拷贝构造
StackOnly obj4 = StackOnly::CreateObj();
StackOnly obj5(obj4);
StackOnly obj6 = obj4;
// 但是用拷贝构造创建堆区对象: 于是可以禁用new
// StackOnly* obj7 = new StackOnly(obj4);
// 问题: 静态区创建对象
static StackOnly obj8(obj4);
return 0;
}
class StackOnly
{
public:
static StackOnly CreateObj()
{
return StackOnly();
}
// 禁用拷贝构造, 打开移动构造
StackOnly(StackOnly&&){}
StackOnly(const StackOnly&) = delete;
private:
StackOnly()
{}
};
int main()
{
// StackOnly obj1;
// static StackOnly obj2;
// StackOnly* obj3 = new StackOnly();
// 此时采用: 移动构造
StackOnly obj4 = StackOnly::CreateObj();
// StackOnly obj5(obj4);
// StackOnly obj6 = obj4;
// StackOnly* obj7 = new StackOnly(obj4);
// static StackOnly obj8(obj4);
// 问题: 移动构造创建对象
static StackOnly obj8(move(obj4));
StackOnly* obj9 = new StackOnly(move(obj4));
return 0;
}
5.设计类:只能创建一个对象(单例模式)
- 设计模式:反复使用,多数人知晓、经过分类的、代码设计经验的总结。
- 单例模式:一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。
- 迭代器模式、适配器模式、单例模式、策略模式、观察者模式、工厂模式、装饰器模式等…
单例模式有两种实现模式:饿汉模式和懒汉模式
// 饿汉模式存在问题
// 1. 多个饿汉模式的单例,某个对象初始化内容较多(读文件),会导致程序启动慢
// 2. A和B两个饿汉,对象初始化存在依赖关系,要求A先初始化,B再初始化,无法保证
class InfoMar
{
public:
static InfoMar& GetInstance()
{
return _ins;
}
private:
InfoMar()
{
cout << "ip:" << _ip << endl;
cout << "port: " << _port << endl;
}
// 禁用: 拷贝构造和拷贝赋值
InfoMar(const InfoMar&) = delete;
InfoMar& operator=(const InfoMar&) = delete;
private:
string _ip = "127.0.0.1";
int _port = 8080;
// 静态对象与普通对象不同: 不在类中, 而是在静态区, 类域的限制
static InfoMar _ins;
};
// 静态成员: 类内声明, 类外定义
InfoMar InfoMar::_ins;
int main()
{
// 程序运行在该行: 静态对象就被创建好了
InfoMar::GetInstance();
return 0;
}
// 懒汉模式: 解决饿汉模式的两个问题
class InfoMar
{
public:
static InfoMar& GetInstance()
{
// 第一次调用时创建单例对象
// 存在线程安全问题
if (_pins == nullptr)
{
_pins = new InfoMar;
}
return *_pins;
}
static void DelInstance()
{
delete _pins;
_pins = nullptr;
}
private:
InfoMar()
{
cout << "ip:" << _ip << endl;
cout << "port: " << _port << endl;
}
// 禁用: 拷贝构造和拷贝赋值
InfoMar(const InfoMar&) = delete;
InfoMar& operator=(const InfoMar&) = delete;
private:
string _ip = "127.0.0.1";
int _port = 8080;
static InfoMar* _pins;
};
InfoMar* InfoMar::_pins = nullptr;
int main()
{
InfoMar::GetInstance();
return 0;
}
// 懒汉模式2: 推荐
class InfoMar
{
public:
static InfoMar& GetInstance()
{
// 局部静态: 再第一次调用时创建单例对象
// C++11之后
static InfoMar ins;
return ins;
}
private:
InfoMar()
{
cout << "ip:" << _ip << endl;
cout << "port: " << _port << endl;
}
// 禁用: 拷贝构造和拷贝赋值
InfoMar(const InfoMar&) = delete;
InfoMar& operator=(const InfoMar&) = delete;
private:
string _ip = "127.0.0.1";
int _port = 8080;
};
int main()
{
InfoMar::GetInstance();
return 0;
}