C++ primer学习笔记(四)

运算符重载为非成员函数(友元)
规则:

• 函数的形参代表依自左至右次序排列的各操作数(所有操作数)。
• 重载为非成员函数时:
	○ 参数个数=原操作数个数(后置++、--除外)
	○ 至少应该有一个自定义类型的参数。
• 后置单目运算符 ++和--的重载函数,形参列表中要增加一个int,但不必写形参名。
• 如果在运算符的重载函数中需要操作某类对象的私有成员,可以将此函数声明为该类的友元(比通过类的公有接口访问私有数据成员效率高)。

双目运算符(双目运算符有两个操作数,通常在运算符的左右两侧,)
双目运算符重载为类的成员函数时,函数只显式说明一个参数,该形参是运算符的右操作数,因为成员函数用this指针隐式地访问了类的一个对象,它充当了运算符函数最左边的操作数。

<对象名>.operator <运算符>(<参数>)  //obj1.operator<运算符>(OBJ obj2)
等价于
<对象名><运算符><参数>   //obj1<运算符>obj2

例如  a+b  等价于   a.operator+(b)

单目运算符重载:

逻辑非运算符:!、按位取反运算符:~、自增自减运算符:++, - - 等
前置单目:
<运算符> obj    
相当于
obj.operator<运算符>();

例如:
++a 相当于 a.operator++();

后置单目:运算符重载为类的成员函数时,函数要带有一个整型形参。
obj <运算符>  
相当于
obj.operator<运算符>(int);

例如:
a++ 相当于 a.operator++(int);

非成员函数:
 friend 函数类型 operator 运算符(参数表){
  函数体;
  }

双目运算符 B重载后,
表达式 oprd1 B oprd2
等同于 operator B(oprd1,oprd2 )
前置单目运算符 B重载后,
表达式  B oprd 
等同于  operator B(oprd )
后置单目运算符 ++和--重载后,
表达式 oprd B
等同于operator B(oprd,0 )

举例:
//前置++运算符重载
friend 函数类型 & operator++(类类型 &);
//后置++运算符重载
friend 函数类型 & operator++(类类型 &,int);

初识虚函数:

一般成员函数可以是虚函数
构造函数不能是
析构函数可以是

作用:

实现多态,父类指针指向子类对象,让函数结果实现在编译时或者运行时决定。大体就是让指向父类型的指针指向继承它的子类的函数,从而达到多态性,声明为虚函数,在派生类中要重新定义,如果父类指针单指函数,就表现为子类的特征,如果加入限定符,就表现为某一类中的虚函数特性。

虚函数成员:

声明:
virtual 函数类型 函数名(形参表);

虚函数声明只能出现在类定义的函数原型声明中,不能在函数定义的时候

在派生类中可以对基类的成员函数(添加virtual关键字的虚函数)进行覆盖
虚函数一般不声明内联函数,因为对虚函数的调用需要动态绑定,而对内联函数的处理是静态的

虚表:

每一个多态类有一个虚表(virtual table)
虚表中有当前类的各个虚函数的入口地址
每一个对象有一个指向当前类的虚表的指针(虚指针vfptr)

动态绑定的实现:

构造函数中为对象的虚指针赋值
通过多态类型的指针或引用调用成员函数时
通过虚指针找到虚表,进而找到所调用的虚函数的入口地址
通过该入口地址调用虚函数

抽象类:

• 纯虚类纯虚函数是一个在基类中声明的虚函数,它在该基类中没有定义具体的操作内容,要求各派生类根据实际需要定义自己的版本,纯虚函数的声明格式为:
• virtual 函数类型 函数名(参数表) = 0;//不表示函数运行结果为0,表示它没有函数体
• 带有纯虚函数的类称为抽象类
class 类名
{ 
virtual 类型 函数名(参数表)=0;
 //其他成员…… 
}

抽象类只能作为基类来使用

override:
	多态行为的基础:基类声明虚函数,继承类声明一个函数覆盖该虚函数
	覆盖要求: 函数签名(signature)完全一致
	函数签名包括:函数名 参数列表 const
	
final:
	C++11提供的final,用来避免类被继承,或是基类的函数被改写
	格式:
	virtual 函数类型 函数名(形参列表)final ;
	避免被派生类继承

虚基类是解决类成员标识二义性和信息冗余问题的类,是实现动态多态性的基础

第九章 模板与群体数据(相同类型数据)

如果只是处理数据类型不同,推荐使用模板
例子:
template<typename或者class T>//函数模板
T abs(T x) {
return x<0?-x:x;
}

注意:

一个函数模板并非自动可以处理所有类型的数据
只有能够进行函数模板中运算的类型,可以作为类型实参
自定义的类,需要重载模板中的运算符,才能作为类型实参

类模板:

主要目的就是能够处理不同类型的数据

声明:

template <class T>
class 类名{类内声明}

在类模板以外定义其他成员函数,采取:

template <class T>
T 类名<模板参数 标识符列表>::函数名(参数表)

群体概念:

• 群体是指由多个数据元素组成的集合体。群体可以分为两个大类:线性群体和非线性群体。
• 线性群体中的元素按位置排列有序,可以区分为第一个元素、第二个元素等。
• 非线性群体不用位置顺序来标识元素。
• 线性群体中的元素次序与其逻辑位置关系是对应的。在线性群体中,又可按照访问元素的不同方法分为直接访问、顺序访问和索引访问。

直接访问:线性群体——数组类
静态数组具有固定元素个数,通过下标直接访问
缺点:编译时大小确定,运行时不能更改大下
动态数组可以扩充位置,由任意数量相同类型元素组成
优点:程序运行时可以更改
为什么有的函数返回引用?
如果一个函数返回值是一个对象的值,就是右值,不能成为左值,类似于交换函数
如果返回的是引用,引用是对象的别名, 通过返回引用可以更改对象的值,因此是左值
顺序访问的线性群体——链表类
• 链表是一种动态数据结构,可以表示此类群体
• 链表是由一系列节点组成,节点可以在运行时动态生成
• 每一个节点包括数据域和指向链表下一个结点的指针(),如果链表每一个节点中只有一个指向后继节点的指针,则该链表为单链表

栈是只能从一端访问的线性群体,是一种后进先出的数据结构
栈的三种状态:栈空、栈满、一般状态
栈的基本操作:初始化、入栈、出栈、清空栈、访问栈顶元素、检测栈的状态

队列是只能向一端添加元素,从另一端删除元素的线性群体
队列的三种状态:队空、队满、一般状态

循环队列:在想象中将数组弯曲成环形,元素出队时,后续元素不移动,每当队尾达到数组最后一个元素时,便再回到数组开头,将存储空间的第一个位置作为队尾。可以防止伪溢出的发生。

数据元素:
关键字:
排序:

两种操作:
	○ 比较两个数据的大小
	○ 调整元素在序列中的位置

插入排序思想:每一步将待排序元素按关键字值的大小插入到已排序的适当位置上

选择排序思想:每次从待排序序列中选择关键序最小的元素,(当需要按照关键字升序排列时)顺序排在已排序的最后,直到全部排完

交换排序思想:两两比较待排序中的元素,并交换不满足排序顺序要求的各对元素,直到全部满足顺序要求为止

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值