C++ 08限制构造+智能指针

一、限制构造

限制构造:限制类直接定义对象(实现一些特殊的操作,例如单例设计模式)
方法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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值