C++基础知识五

一、智能指针
智能指针的行为类似常规指针,重要的区别是它负责自动释放所指向的对象。标准库提供的两种智能指针的区别在于管理底层指针的方法不同,shared_ptr允许多个指针指向同一个对象,unique_ptr则“独占”所指向的对象。标准库还定义了一种名为weak_ptr的伴随类,它是一种弱引用,指向shared_ptr所管理的对象,这三种智能指针都定义在memory头文件中。

#include <iostream>
#include <memory>

using namespace std;

class Test
{
    public:
        Test()
        {
            cout<<"Test的构造函数"<<endl;
        }
        ~Test()
        {
            cout<<"Test的析构函数"<<endl;
        }

        void print()
        {
            cout<<"XXXX"<<endl;
        }
};

void f1()
{
    Test *t1 = new Test;
}

void f2()
{
    auto_ptr<Test> my_memory(new Test);
    my_memory->print();
}

int main(int argc, char const *argv[])
{
    f1();
    f2();
    return 0;
}

在这里插入图片描述

二、模板
2.1 概念:将函数的返回值和参数的类型参数化,也叫范型编程

2.2 函数模板

#include <iostream>
using namespace std;

int add(int x, int y)              //当模板函数和原函数同时存在时,优先调用原来的函数
{
    cout<<"int add(int x, int y)"<<endl;
    return x + y;
}

double add(double x, double y)
{
    cout<<"double add(double x, double y)"<<endl;
    return x + y;
}

template <typename T>          //声明一个虚拟类型T,模板函数不能做默认类型转换
T add(T x, T y)
{
    cout<<"template <typename T>"<<endl;
    return x + y;
}

template <typename T1, typename T2>
void print(T1 x, T2 y)
{
    cout<<x<<" "<<y<<endl;
}

int main(int argc, char const *argv[])
{
    cout<<add(1,2)<<endl;          //隐式调用
    cout<<add(1.11,  2.22)<<endl;
    cout<<add<int>(1,'a')<<endl;   //显示调用

    print(1,'a');

    return 0;
}

2.3 类模板
2.3.1 类模板的定义:类模板中定义的函数类型可以用在类声明和类实现中,类模板的目的同样是将数据类型参数化

#include <iostream>
using namespace std;

template <typename T, typename U>
class Test
{
    private:
        T a;
        U b;
    
    public:
        Test(T a, U b)
        {
            this->a = a;
            this->b = b;
        }
        void show()
        {
            cout<<a<<" "<<b<<endl;
        }
};


int main(int argc, char const *argv[])
{
    Test<int,char> t(1,'a');   //类模板创建时一定要显示调用   
    t.show();
     
    return 0;
}

在这里插入图片描述
类模板中的继承

#include <iostream>

using namespace std;

template <typename T, typename U>
class Parent
{
    protected:
        T a;
        U b;
    public:
        Parent(T a, U b)
        {
            this->a = a;
            this->b = b;
        }
        void show()
        {
            cout<<a<<" "<<b<<endl;
        }
};

class Child:public Parent<int, char>     //模板类派生普通类,继承的同时对基类实例化
{
    public:
        Child(int a, char b):Parent(a,b)
        {

        }
        void show()
        {
            cout<<a<<" "<<b<<endl;           
        }
};

template <typename T, typename U>
class Child2:public Parent<T,U>     //模板类派生模板类,继承的同时不需要对parent进行实例化
{
    private:
        U c;
    public:
        Child2(T a, U b, U c):Parent<T,U>(a,b)
        {
            this->c = c;
        }
        void show()
        {
            cout<<this->a<<" "<<this->b<<" "<<c<<endl;
        }
};

int main(int argc, char const *argv[])
{
    Child c1(1,'a');
    c1.show();

    Child2<int,double> c2(1,2.22,3.33);
    c2.show();
    return 0;
}

在这里插入图片描述
模板的声明

#include <iostream>

using namespace std;

template <typename T>    //类模板的声明的作用域仅对下一个函数或者类有效
class Test
{
    private:
        int a;
    
    public:
        Test(T a);
        void show();
        ~Test();
};

template <typename T>
Test<T>::Test(T a)  //Test<T>表示Test是模板类,不是普通类  
{
    this->a = a;
}

template <typename T>
void Test<T>::show()
{
    cout<<a<<endl;
}

template <typename T>
Test<T>::~Test()   
{
    cout<<"Test的析构函数"<<endl;
}

int main(int argc, char const *argv[])
{
    Test<int> t(1);
    t.show(); 
    return 0;
}

模板中的static关键字

#include <iostream>

using namespace std;

template <typename T>    //类模板的声明的作用域仅对下一个函数或者类有效
class Test
{
    private:
        int a;
    
    public:
        static int count;   //类外面初始化
        Test(T a);
        void show();
        ~Test();
};

template <typename T>
int Test<T>::count = 0;

template <typename T>
Test<T>::Test(T a)  //Test<T>表示Test是模板类,不是普通类  
{
    this->a = a;
}

template <typename T>
void Test<T>::show()
{
    cout<<a<<endl;
}

template <typename T>
Test<T>::~Test()   
{
    cout<<"Test的析构函数"<<endl;
}

int main(int argc, char const *argv[])
{
    Test<int> t1(1);
    Test<int> t2(1);
    Test<int> t3(1);
    Test<int> t4(1);
    Test<int> t5(1);
    Test<int> t6(1);
    Test<char> t7('a');
    Test<char> t8('b');
    Test<char> t9('c');
    Test<char> t10('d');

    cout<<Test<int>::count<<endl;
    cout<<Test<char>::count<<endl;
    
    return 0;
}


三、异常
3.1 什么是异常?
异常处理就是处理程序中的错误,所以错误就是指程序在运行期间的一些异常举动(栈溢出,读取文件不存在,野指针等)
3.2 异常的语法
抛出异常: throw关键词, 当执行throw关键词后,抛出异常
检测异常:try语句会检测异常
捕获异常:catch(异常类型 变量名){处理语句}

#include <iostream>

using namespace std;

int Div(int x, int y)   //除
{
    if(0 == y)
    {
        throw 0; //抛出异常
    }
    return x / y;
}

int main(int argc, char const *argv[])
{
    int a, b;
    cin>>a>>b;

    try
    {
        cout<<Div(a,b)<<endl;
    }
    catch(int)
    {
        cout<<"zero excetion!"<<endl;
    }
    cout<<"hello world"<<endl;
    return 0;
}

3.3 异常的思想

#include <iostream>

using namespace std;

int Div(int x, int y)   //除
{
    if(0 == y)
    {
        throw 0; //抛出异常
    }
    
    return x / y;
}

int main(int argc, char const *argv[])
{
    int a, b;
    cin>>a>>b;

    try   //把可能异常的语句放在try语句中
    {
        cout<<Div(a,b)<<endl;
    }
    catch(int)
    {
        cout<<"zero excetion!"<<endl;
    }
    cout<<"hello world"<<endl;
    return 0;
}

3.4 异常的声明

#include <iostream>

using namespace std;

//int Div(int x, int y) throw(int , char);   //只能抛出整型或者字符型异常
//int Div(int x,int y) throw();  //不能抛出任何异常
int Div(int x,int y);   //可能抛出任何异常


int main(int argc, char const *argv[])
{
    int a, b; 
    cin>>a>>b;
    try
    {
        cout<<Div(a,b)<<endl;
    }
    catch(int)
    {
        cout<<"zero exception"<<endl;
    }
    catch(char)
    {
        cout<<"char exception"<<endl;
    }
    catch(double)
    {
        cout<<"double exception"<<endl;
    }
       
    cout<<"hello world"<<endl;
    return 0;
}
int Div(int x, int y)   //除
{
    if(0 == y)
    {
        throw 1.11; //抛出异常
    }
    
    return x / y;
}

3.5 异常的对象

#include <iostream>
using namespace std;

class Test
{
    public:
        Test()
        {
            cout<<"Test的构造函数"<<endl;
        }
        Test(const Test &is_obj)  //拷贝构造函数
        {
            cout<<"Test的拷贝构造函数"<<endl;
        }
        void print()
        {
            cout<<"Test exception"<<endl;
        }
        ~Test()
        {
            cout<<"Test的析构函数"<<endl;
        }
};

int Div(int x, int y)   //除
{
    if(0 == y)
    {
        //throw 1.11; //抛出异常
        throw new Test;
    }
    
    return x / y;
}

int main(int argc, char const *argv[])
{
    int a, b;
    cin>>a>>b;

    try
    {
        cout<<Div(a,b)<<endl;
    }
    catch(Test t)  //调用了拷贝构造函数
    {
        t.print();
    }
    catch(Test &t)   //引用
    {
        t.print();
    }
    catch(Test *t)    //Test *t = new Test;
    {
        t->print();
        delete t;   //需要手动释放
    }


    cout<<"hello world"<<endl;
    return 0;
}

3.6 标准异常库
execption基类提供一个函数:what(),用于返回错误信息
virtual const char * what() const throw();

//exception 基类提供了一个函数: what() 用于返回错误信息
//virtual const char * what()const throw();
#include <iostream>
#include <exception>

using namespace std;

class Test
{
    private:
        int id;
    public:
        Test(int i)
        {
            if(i < 0)
            {
                throw out_of_range("id不可以小于0");
            }

            id = i;
        }
};

int main(int argc, char const *argv[])
{
    try
    {
        Test t(-1);
    }
    catch(exception& e)
    {
        cout << e.what() << '\n';
    }
    
    return 0;
}

类型转换

C语言强制类型转换存在的问题
1.过于粗暴
2.难于定位

C++中的类型转换
static_cast 强制类型转换
限制条件:1.用于基本类型之间的转换,不能用于普通指针之间的转换
2.用于有继承关系的对象之间的转换和类指针之间的 转换
3.static_cast 是在编译期间进行转换的,无法在运行时检查类型,所以可能存在风险

#include <iostream>

using namespace std;

class Parent
{

};

class  Child:public Parent
{

};

int main(int argc, char const *argv[])
{
    int a = 1;
    char ch = 'a';
    a = static_cast<int>(ch);    //用于普通类型之间的转换
    cout<<a<<endl;

   // int *p = static_cast<int *>(&ch);  //不能用于普通指针之间的类型转换
    Parent p;
    Child c; 

    p = static_cast<Parent>(c);  //用于有继承关系的类对象之间的转换
   // cout<<p<<endl;

    Parent *p1 = static_cast<Parent *>(&c);    //用于类对象指针之间的转换  
    cout<<p1<<endl;
    return 0;

    
}


reinterpret_cast

#include <iostream>

using namespace std;

int main(int argc, char const *argv[])
{
    int a = 100;
    int b = 10;

    char *p = reinterpret_cast<char *>(&a);  //用于普通指针类型之间的转换(不安全)
    cout<<*(p+1)<<endl;

    int *q = reinterpret_cast<int *>(100);   //用于数字和指针之间的转换,很容易出现野指针

    *q = 1;
    
    return 0;
}

const_cast

#include <iostream>
using namespace std;

int main(int argc, char const *argv[])
{
    const int a = 1;   //常量
    int *p = const_cast<int *>(&a);
    *p = 100;
    cout<<a<<endl;

    const int &m = 1;   //常量
    int &n = const_cast<int &>(m);
    n = 100;
    cout<<m<<endl;
    cout<<n<<endl;
    return 0;
}

dynamic_cast

#include <iostream>
using namespace std;

class Parent
{
    public:
        virtual void show()
        {

        }
};

class Child: public Parent
{
    public:
        void show()
        {

        }
};

int main(int argc, char const *argv[])
{
    Child *c = new Child;
    delete c;

    c =  dynamic_cast<Child *>(new Parent);    //派生类指针指向基类对象(错误) 

    if(c == NULL)
    {
        cout<<"转换失败"<<endl;
    }
    else
    {
        cout<<"转换成功"<<endl;
        delete c;
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值