运算符重载、STL模板库、类型转换、异常处理机制(C++五)

一、运算符重载

1. 引入运算符重载

扩展运算符的作用

比如:我自定义了一个类Animal
     Animal  a;
     Animal b; 
     Animal c=a+b

cout<<a<<b<<c<<endl;

2.语法格式

返回值类型  operator+(形参列表)    //表示我想对+进行运算符重载
{

}

注意:“operator+”你可以理解为就是个函数的名字

3.运算符重载有两种表现形式

①把运算符重载作为类的成员函数

规定:左值是函数调用者, 右值函数的参数

class Dog
{
	//对加法进行运算符重载  是Dog的成员函数
	Dog operator+(Dog &otherdog)
	{
		函数体;
	}
};

②把运算符重载作为类的友元函数(注意写法的差异,不能使用this,不属于类的成员函数)

规定:左值为第一个参数, 右值为第二个参数

class Dog
{
	friend Dog operator+(Dog &dog1,Dog &dog2);
};
//定义一个普通函数去重载加法运算
Dog operator+(Dog &dog1,Dog &dog2)
{
	函数体;
}

4.运算符重载分类

单目运算符重载 a++ ++a a-- --a ~a !a

后置++ operator++(int)
前置++ operator++()

双目运算符重载 + - * / % > < !=

5.运算符重载的特点:

①重载运算符不能改变运算符原本的语义

②不能发明新的运算符号

③不能重载

.(成员访问运算符)
.*(成员指针访问运算符)
::(域运算符)
sizeof(数据类型长度运算符)
?:(条件运算符, 三目运算符)

二、C++中的STL模板库的使用

STL: standard template library(标准模板库)

里面提供了大量的模板类,可以划分为如下几种

1.容器类(container)

用来存放大量数据的

向量vector: 连续存储的元素

assign()  //重复使用会覆盖vector前面存放的数据
at(i)  //获取对应下标的元素    myvector[i]
insert() //在指定迭代器位置插入数据
pop_back() //删除最后一个元素
push_back() //尾插

列表list:由节点组成的双向链表,每个结点包含着一个元素

merge()  合并两个链表

集合set:由节点组成的红黑树,每个节点都包含着一个元素,节点之间以某种作用于元素对的谓词排列,没有两个不同的元素能够拥有相同的次序

emplace();   //往set中存放数据
find();  //查找指定元素并返回迭代器

映射map: 由{键,值}对组成的集合,以某种作用于键对上的谓词排列

例如:

星期一monday
星期二tuesday
星期三wensday

栈stack:后进先出的值的排列

队列queue:先进先出的执的排列

2.算法(algorithm)

封装算法用来使用

3.迭代器(iterator)

通俗地理解为就是一个指针,专门指向容器中的某个数据

三、C++的类型转换

1.类型转换名称和语法

C风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是:

TYPE b = (TYPE)a   

C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用。

static_cast         静态类型转换。如int转换成char
reinterpreter_cast  重新解释类型
dynamic_cast        命名上理解是动态类型转换。如子类和父类之间的多态类型转换。
const_cast,        字面上理解就是去const属性。

4种类型转换的格式:

TYPE B = static_cast<TYPE> (a) 

2.类型转换介绍

(1)static_cast<>()

静态类型转换,编译的时c++编译器会做类型检查;

基本类型能转换 但是不能转换指针类型

若不同类型之间,进行强制类型转换,用reinterpret_cast<>() 进行重新解释

结论:

①C语言中能隐式类型转换的,在c++中可用 static_cast<>()进行类型转换。因C++编译器在编译检查一般都能通过;

②C语言中不能隐式类型转换的,在c++中可以用 reinterpret_cast<>() 进行强行类型解释。

总结:static_cast<>()和reinterpret_cast<>() 基本上把C语言中的 强制类型转换给覆盖

(2)reinterpret_cast<>()

很难保证移植性。

(3)dynamic_cast<>()

动态类型转换,安全的基类和子类之间转换;运行时类型检查

(4)const_cast<>()

去除变量的只读属性

(5)static_cast用法和reinterpret_cast用法

int  main(void)
{
        double dPi = 3.1415926;

        //1静态的类型转换:  在编译的时 进行基本类型的转换 能替代c风格的类型转换 可以进行一部分检查
        int num1 = static_cast<int> (dPi); //c++的新式的类型转换运算符 
        int num2 = (int)dPi;                             //c语言的 旧式类型转换
        int num3 = dPi;                                  //隐士类型转换
        cout << "num1:" << num1 << " num2:" << num2 << " num3:" << num3 << endl;


        char *p1 = "hello world" ;
        int *p2 = NULL;
        p2 = (int *)p1;

        //2 基本类型能转换 但是不能转换指针类型
        //p2 = static_cast<int *> (p1); //“static_cast”: 无法从“char *”转换为“int *”

        //3 可以使用  reinterpret_cast 进行重新解释
        p2 = reinterpret_cast<int *> (p1);
        cout << "p1 " << p1 << endl;
        cout << "p2 " << p2 << endl;

        //4结论:      
        //c语言中能隐式类型转换的 在c++中可以用 static_cast<>()进行类型转换  //C++编译器在编译检查一般都能通过
        //c语言中不能隐式类型转换的,在c++中可以用 reinterpret_cast<>() 进行强行类型 解释
       
        return 0;
}

(6)dynamic_cast用法和reinterpret_cast用法

class Animal{
public:
         virtual void  cry() = 0;
};
class Dog : public Animal{
public:
         virtual void  cry(){
                   cout << "wangwang " << endl;
         }
         void doSwim() {
                   cout << "我要狗爬" << endl;
         }
};
class Cat : public Animal{
public:
         virtual void  cry(){
                   cout << "miaomiao " << endl;
         }
         void doTree() {
                   cout << "我要爬树" << endl;
         }
};
class Book{
public:
         void printP(){
                   cout << price << endl;
         }
private:
         int price;
 
};
 
void ObjPlay(Animal *base){
         base->cry();
         Dog *pDog = dynamic_cast<Dog *>(base);
         if (pDog != NULL){
                   pDog->cry();
                   pDog->doSwim();
         }
         Cat *pCat = dynamic_cast<Cat *>(base);
         if (pCat != NULL){
                   pCat->cry();
                   pCat->doTree();
         }
}
int main(void){
         Animal *base = NULL;
         //1 可以把子类指针赋给 父类指针 但是反过来是不可以的需要如下转换
         //pdog = base; 
         Dog *pDog = static_cast<Dog *> (base);
         //2 把base转换成其他非动物相关的 err
         //Book *book= static_cast<Book *> (base);
 
         //3  reinterpret_cast //可以强制类型转换
         Book *book2= reinterpret_cast<Book *> (base);
 
         //4 dynamic_cast用法
         ObjPlay(new Cat());
 
         return 0;
}

四、异常处理机制

1.异常基本语法

①若有异常则通过throw操作创建一个异常对象并抛掷。

② 将可能抛出异常的程序段嵌在try块之中。控制通过正常的顺序执行到达try语句,然后执行try块内的保护段。

③ 如果在保护段执行期间没有引起异常,那么跟在try块后的catch子句就不执行。程序从try块后跟随的最后一个catch子句后面的语句继续执行下去。

④ catch子句按其在try块后出现的顺序被检查。匹配的catch子句将捕获并处理异常(或继续抛掷异常)。

⑤ 如果匹配的处理器未找到,则运行函数terminate将被自动调用,其缺省功能是调用abort终止程序。

⑥处理不了的异常,可以在catch的最后一个分支,使用throw语法,向上扔。

例子

int divide(int x, int y )
{
	if (y ==0)
	{
		throw x;
	}
	return x/y;
}
int main(void)
{
	try
	{
		cout << "8/2 = " << divide(8, 2) << endl;
		cout << "10/0 =" << divide(10, 0) << endl;
	}
	catch (int e)
	{
		cout << "e" << " is divided by zero!" << endl;
	}
	catch(...)
	{
		cout << "未知异常" << endl;
	}
	cout << "ok" << endl;
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java.L

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值