一、限制构造
限制构造:限制类直接定义对象(实现一些特殊的操作,例如单例设计模式)
方法1:将构造函数隐藏到private,通过友元函数或静态函数获取对象
方法2:将构造函数隐藏到protected,通过静态函数,或者友元函数,或者继承来使用
static A* init(int x)
{
A* ptr=new A(x); //new在堆区,防止对象在函数结束时被销毁,
return ptr; //但是注意要手动的delete内存,以防止内存泄漏
}
简单的单例设计模式
class Singleton{
private:
static Sinleton* instance;
Singleton(){} //将构造函数设为私有,防止外部创建实例
public:
static Singleton * getInstance()
{
if(instance == nullptr) //判断,如果有对象了,就把该指针返回回去,
{ //使得多次定义不同对象时,对象都指向了一个空间(实体)
instance == new Singleton();
}
return instance;
}
freeInstance()
{
if(instance!=nullptr)
{
delete instance;
instance = nullptr;
}
}
void showMessage()
{
std::out<<"hello world!"<<std::endl;
}
};
Singleton* Singleton::instance = nullptr;
int main()
{
Singleton * singleton = Singleton::getInstance();
singleton->showMessage();
Singleton *ptr = Singleton ::getInstance();
ptr->showMessage();
ptr->freeInstance();
return 0;
}
1.将构造函数隐藏到private,通过友元函数或静态函数获取对象
#include <iostream>
using namespace std;
// 限制构造: 将构造函数 修饰为private
// 限制构造意义: 可以用来实现单例设计模型
class A
{
public:
void print_val(void)
{
cout << "val:" << val << endl;
}
//--------------------------------------------------------------------
static A *get_obj(int x) // 通过静态函数 获取对象
{
A *ptr = new A(x); //new在堆区,防止对象在函数结束时被销毁,
return ptr; //但是注意要手动的delete内存,以防止内存泄漏
}
//--------------------------------------------------------------------
static void free_obj(A *ptr)
{
delete ptr;
}
~A()
{
cout << "A析构" << endl;
}
private:
int val;
A(int x = 0) : val(x)
{
cout << "A构造" << endl;
}
friend A *get_instance(int x);
};
//--------------------------------------------------------------------
// 通过友元函数实现
A *get_instance(int x)
{
A *ptr = new A(x);
return ptr;
}
//--------------------------------------------------------------------
int main(void)
{
// A a1(354);
// a1.print_val();
A *ptr = A::get_obj(354); //通过静态函数获取对象 静态函数使用 类域::函数
ptr->print_val();
A::free_obj(ptr); //通过静态函数释放对象
#if 0
A *ptr = get_instance(1234);
ptr->print_val();
delete ptr;
#endif
return 0;
}
必须返回指针,不能返回对象,返回对象需要外部有一个对象来接收,但是外部不能定义对象(被private限制了)
2.将构造函数隐藏到protected,通过静态函数,或者友元函数,或者继承来使用
#include <iostream>
using namespace std;
//限制构造: 将构造函数 修饰为protected
class A
{
protected:
A(int x=0){
cout<<"A构造"<<endl;
}
};
//可以用来 继承来使用
class B:public A
{
};
int main(void)
{
// A a1;
// A a2(34);
B b1; //构造子类时,父类也会构造
return 0;
}
二、智能指针
注意包含头文件:#include <memory>
背景:对于new开辟的空间,需要delete释放,如果忘记delete会造成内存泄露
因此C++设计了智能指针,用于解决该问题
智能“指针”,其实这里的指针不是真正的指针,是对象,是通过运算符重载,实现类似指针的操作,例如-> 、* ;
智能指针的实现依赖:类模板 + 运算符重载 + 浅拷贝 + 引用计数器的设计
shared_ptr //共享智能指针,多个指针可以指向同一对象(允许拷贝构造,赋值操作)
unique_ptr //唯一智能指针,避免出现安全问题 ,不允许多个指针指向同一对象(禁止拷贝,赋值)
wake_ptr // 用于管理的共享智能指针,提供了一个方法用于判断对象是否存在 ,是shared_ptr更加安全
1.shared_ptr
shared_ptr <Demo> ptr (new Demo); //模板类
或
shared_ptr <Demo> ptr = make_shared <Demo>(Demo());
ptr实质,是一个对象
------------------------------------------------------------------------------
共享智能指针 允许拷贝构造与赋值函数
拷贝构造:
shared_ptr <A> ptr2(ptr1);
赋值操作:
shared_ptr <A> ptr3(new A(11)); //又单独开一片空间,方便演示
ptr3=ptr2;
ptr2和ptr1指向的是同一片空间
eg:
#include <iostream>
#include <memory>
using namespace std;
class A
{
private:
int i;
public:
A(int x=0): i(x) {
cout<<"A构造"<<endl;
}
~A(){
cout<<"A析构"<<endl;
}
void set_val(int x){
i = x;
}
void print_val(void){
cout<<"i:"<<i<<endl;
}
};
int main(void)
{
// A *ptr = new A(12);
// ptr->print_val();
shared_ptr <A> ptr1 (new A(12));
ptr1->print_val();
(*ptr1).set_val(200);
(*ptr1).print_val();
//共享智能指针 允许拷贝构造与赋值函数使得指针指向同一片空间
shared_ptr <A> ptr2(ptr1);
ptr2->set_val(123);
ptr1->print_val();
shared_ptr <A> ptr3(new A(11));
ptr3 = ptr1;
return 0;
}
2.unique_ptr
unique_ptr <Demo> ptr <new Demo>;
唯一指针:不允许拷贝构造和赋值函数(拷贝构造和赋值函数被删掉了)
eg:
unique_ptr <A> ptr (new A(12));
eg:
#include <iostream>
#include <memory>
using namespace std;
class A
{
private:
int i;
public:
A(int x=0): i(x) {
cout<<"A构造"<<endl;
}
~A(){
cout<<"A析构"<<endl;
}
void set_val(int x){
i = x;
}
void print_val(void){
cout<<"i:"<<i<<endl;
}
};
int main(void)
{
// A *ptr = new A(12);
// ptr->print_val();
unique_ptr <A> ptr1 (new A(12));
ptr1->print_val();
(*ptr1).set_val(200);
(*ptr1).print_val();
#if 1
//唯一指针 不允许拷贝构造与赋值函数
// unique_ptr <A> ptr2(ptr1); //不允许拷贝构造
//ptr2->set_val(123);
//ptr1->print_val();
unique_ptr <A> ptr3(new A(11));
//ptr3 = ptr1; //不允赋值操作
#endif
return 0;
}
3.wake_ptr
普通写法:
shared_ptr <Demo> ptr1 (new Demo());
weak_ptr <Demo> w_ptr(ptr1); //w_ptr用于管理共享智能指针
比较安全的写法:
shared_ptr <Demo> ptr1 = make_shared <Demo> (Demo()); //比较安全
//如果是shared_ptr <A> ptr1 (&obj); //obj是一个栈区的对象 Demo obj;
//栈区对象是自动开辟自动释放的,上述操作将共享指针指向栈区,共享指针free的时候发现是栈区的会出现问题
weak_ptr <Demo> ptr2=ptr1;
---------------------------------------------------------------------------------
w_ptr:
if(w_ptr.expired()) //判断对象是否销毁了
{
cout<<"对象已经销毁了"<<endl;
}
w_ptr.reset(); //可以用来释放对象
---------------------------------------------------------------------------------
eg:
shared_ptr <A> ptr1 (new A(123));
weak_ptr <A> w_ptr(ptr1); //weak_ptr用于管理共享智能指针
eg:
#include <iostream>
#include <memory>
using namespace std;
class A
{
private:
int i;
public:
A(int x=0): i(x) {
cout<<"A构造"<<endl;
}
~A(){
cout<<"A析构"<<endl;
}
void set_val(int x){
i = x;
}
void print_val(void){
cout<<"i:"<<i<<endl;
}
};
int main(void)
{
//shared_ptr <A> ptr1 (&obj);
//shared_ptr <A> ptr1 = make_shared <A>(A()); //更加安全的写法
shared_ptr <A> ptr1 (new A(123));
weak_ptr <A> w_ptr(ptr1); //weak_ptr用于管理共享智能指针
//w_ptr.reset();
if(w_ptr.expired()){
cout<<"对象已经销毁了"<<endl; //不能使用共享智能指针
}
else{
ptr1->print_val();
}
return 0;
}
三、异常处理
异常处理思想:分离思想
将问题监测和问题处理相分离 :出现异常暂时性不做处理,抛出异常,留给使用者去处理
基本流程:三个部分组成
try(检查)----throw(抛出)-----catch(捕获)
异常会一级一级抛出,到最高一级还无法处理的话,运行系统会自动调用系统函数treminate
捕获类型,需要按类型进行捕获
#include <iostream>
using namespace std;
// 定义数组类
class Array
{
private:
int *data;
int len;
int index;
public:
Array(int len = 20)
{
#if 1
if (len <= 0)
{
throw "len error"; // 抛出异常
}
#endif
data = new int[len]; // 开辟空间
this->len = len;
this->index = -1;
}
Array(const Array &obj)
{ // 拷贝构造
this->len = obj.len;
this->index = obj.index;
this->data = new int[obj.len];
for (int i = 0; i <= index; i++)
{
this->data[i] = obj.data[i];
}
}
~Array()
{
delete[] data; // 释放空间
}
bool full()
{
if (index == len - 1)
{
return true;
}
else
{
return false;
}
}
bool empty()
{
if (index == -1)
{
return true;
}
else
{
return false;
}
}
int push_back(int val)
{
if (full())
{
return -1;
}
index++;
data[index] = val;
return 0;
}
int print()
{
for (int i = 0; i <= index; i++)
{
cout << data[i] << ",";
}
cout << endl;
return 0;
}
int at(int index)
{
if (index < 0 || index > this->index)
{
throw "index error"; //异常类型 可以是基本类型 也可以是对象
}
return data[index];
}
int lenth()
{ // 数组有效数据长度
return index + 1;
}
int space()
{ // 数组空间大小字节数
return sizeof(int) * len;
}
int &operator[](int i)
{
if (i < 0 || i > this->index)
{
throw -1;
}
return data[i];
}
};
int main(void)
{
try
{
Array a1(-100);
a1.push_back(54);
a1.push_back(83);
a1.push_back(182);
a1.at(-5);
a1[-10];
a1.print();
}
//根据类型 进行捕获,然后进行处理
catch (const char *str)
{
cout << str << endl;
}
catch (const int errnum){
cout<< errnum<<endl;
}
catch (const std::exception &e)
{
std::cerr << e.what() << '\n';
}
return 0;
}