C++期末复习⼩整理(三)
C++课上整理及思考
1.绪论
C++融合了三种不同的⽅法,
⾯向过程的编程:C++继承了C语⾔⾼效、简洁、快速和可移植性的传统
(⾃顶向下、逐步求精结构化编程技术反映了过程性编程的思想,根据可执⾏的操作来构思⼀个程序)基于对象和⾯向对象的编程:C++在C语⾔基础上添加,C++的核⼼概念就是类
(强调数据,让语⾔来满⾜问题的要求 类和对象 ⾃下向上(bottom-up)编程
有助于创建可重⽤的代码)
泛型编程:C++模板特性⽀持
(强调算法 创建独⽴于类型的代码)
C++与C保持兼容,C++不是⼀个纯正的⾯向对象的语⾔
类的分类:
抽象类:
含有纯虚函数的类被称为抽象类。抽象类只能作为派⽣类的基类,不能定义对象,但可以定义指针。抽象类为类族建⽴⼀个公共的接⼝,更好的发挥多态性
基类
派⽣类
⾯向对象程序设计的特点
封装性
继承性
多态性
继承对于软件复⽤有着重要意义,是⾯向对象技术能够提⾼软件开发效率的重要原因之⼀。
2.简单程序设计
字符集:
字母
包括⼤写英⽂字母A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
和⼩写英⽂字母a b c d e f g h i j k l m n o p q r s t u v w x y z
数字
0 1 2 3 4 5 6 7 8 9
特殊符号
/ = , . _ : ; ? \ ” ’ ~ | ! # % & ( ) [ ] { } ^ < > 空格。
关键字
bool true false const enum wchar_t
const_cast dynamic_cast static_cast reinterpret_cast
class public private protected friend inline mutable this virtual
try catch throw
new delete
explicit
namespace using
operator
template typename typeid
union volatile
asm export
标识符
标识符是⼀个以字母或下划线开头的,由字母、数字、下划线组成的字符串。
标识符不能与任意⼀个关键字同名。
标识符中的字母区分⼤⼩写。
标识符不宜过长。
运算符
单字符组成的运算符:例如,+,-,,/等。
双字符组成的运算符:例如, ++,<=,&&,=,->等。
三个字符组成的运算符:例如,<<=,>>=等。
关键字运算符:new,delete,sizeof等(这⼏个运算符平时定义很少有注意)
最短的C++程序
int main() { }
C++中⼀般⽤const来代替C语⾔中的#define
然⽽我们使⽤const的时候,我们注意:
声明时⼀定要赋初值,⽽且在程序中不能改变其值
Ex:
const int N; (要赋初值)
N = 100; (常量不可以被赋值)
#define与const的区别:
#define
#define PI 3.14
只在预处理期间存在,不占⽤存储空间
能放在⼀个头⽂件⾥
没有类型信息,可能会隐藏错误
const
const double PI=3.1415;
const double PI(3.1415);
默认为内部连接
可不必创建内存(是否创建内存依赖于对它如何使⽤)
可放在头⽂件中,是安全的
extern const int x=0; 强迫为它分配内存
const有两层含义,
⽤来声明值不可改变的量,等同于C语⾔中的意义
⽤来声明可以在编译期确定其值的量,这类似于C语⾔的#define。
如果⼀个量的值确实可以在编译期算出来,那么编译器将尽可能对其进⾏优化,在之后⽤到此量的地⽅都直接⽤其值来代替,从⽽减少对内存的访问,以达到和#define相同的效率。
C++中的const关键字的⽤法⾮常灵活,使⽤const将⼤⼤改善程序的健壮性
const int MONTH=12; //必须给定初值
const 与正常变量⼀样有作⽤域
可以节省空间,避免不必要的内存分配
const doulbe Pi=3.14159; //此时并未将Pi放⼊ROM中
double i=Pi; //此时为Pi分配内存,以后不再分配
double j=Pi; //没有内存分配
编译器通常不为普通const常量分配存储空间,⽽是将它们保存在符号表中,这使得它成为⼀个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很⾼
C++中的四种显式转换(强制转换)注意⼀下
3.函数
函数的参数和返回值的传递⽅式有:
值传递
指针传递
引⽤传递:传递的性质象指针传递,使⽤⽅式像值传递
引⽤传递:
引⽤,是⼀个变量的别名。
变量名和别名实际上都是指向同⼀个实体(所以地址相同也当然了)。
&不可以放在void和别名之间。
声明⼀个别名引⽤时,必须同时对它进⾏初始化(这⼀点和我们的指针很相似),使它指向⼀个已存在的对象
⼀旦⼀个引⽤初始化后,就不能改成引⽤其他对象
引⽤从它诞⽣之时起,就必须确定是哪个变量的别名,⽽且始终只能作为这个变量的别名,不能另作他⽤
引⽤必须与合法的存储单元关联,不能有NULL引⽤
引⽤不分配内存和⽣成新的变量
不能为常量指定别名
不允许引⽤数组
使⽤别名的引⽤调⽤在调⽤函数时,实际上是为实参指定⼀个别名(函数的形参),在内存中什么也没做
在被调函数内,对形参(别名)的任何操作直接反映到实参
使⽤引⽤调⽤的⽬的就是使⽤被调函数来修改主调函数中变量的值
在传值调⽤时,有变量的两个不同的拷贝
在⽤别名的引⽤调⽤时,只有⼀份参数变量的拷贝
传递的性质像指针传递,使⽤⽅式像值传递
指针“指向”内存中的某个对象,引⽤“绑定到”内存中的某个对象,它们都实现了对其他对象的间接访问。
区别:
指针本⾝就是⼀个对象,允许对指针赋值和拷贝,⽽且在指针的⽣命周期内它可以指向不同的对象。引⽤不是⼀个对象,⽆法令引⽤引⽤重新绑定到另外⼀个对象
指针⽆须在定义时赋初值,如果在块内没有被初始化,将拥有⼀个不确定的值。引⽤则必须在定义时赋初值。
内联函数不是在调⽤时发⽣控制转移,⽽是在编译时将函数体嵌⼊在每⼀个调⽤处,节省了参数传递、控制转移等开销。
C++规则指出,inline关键字只是对编译器的请求。根据编译器的效率情况,有时它会忽略这个请求,把函数作为普通函数进⾏编译。
内联函数代码⽣成中的⼀种危险情况是内联长函数,占⽤更⼤空间存储多次函数调⽤所造成的更长的代码
如果内联函数体内出现循环语句或switch,那么执⾏函数体内代码的时间要⽐函数调⽤的开销⼤
对内联函数不能进⾏异常接⼝声明
参数缺省值只能出现在函数的声明中,⽽不能出现在函数的定义的头部
默认形参值必须从右向左顺序声明。
在默认形参值的右⾯不能有⾮默认形参值的参数。
默认参数只能⽤常量表达式初始化
PS:
Cstdlib
求随机数
RAND_MAX
int rand(void); //求出并返回⼀个随机数
void srand(unsigned int seed); //为使rand()产⽣⼀系列伪随机数⽽设置起始点。
如果参数是指针,且仅作输⼊⽤,则应在类型前加const,以防⽌该指针在函数体内被意外修改。
如果输⼊参数以值传递的⽅式传递对象,则宜改⽤“const &”⽅式来传递,这样可以省去临时对象的构造和析构过程,从⽽提⾼效率。
有时候函数原本不需要返回值,但为了增加灵活性,如⽀持链式表达,可以附加返回值。
如果函数的返回值是⼀个对象,有些场合⽤“引⽤传递”替换“值传递”可以提⾼效率。⽽有些场合只能⽤“值传递”⽽不能⽤“引⽤传递”,否则会出错。
return 语句不可返回指向“栈内存”的“指针”或者“引⽤”,因为该内存在函数体结束时被⾃动销毁。
要搞清楚返回的究竟是“值”、“指针”还是“引⽤”
如果函数返回值是⼀个对象,要考虑return 语句的效率。
⾯向对象程序设计的基本特点
抽象、封装、继承、多态。
类中成员的访问⽅式:
类中成员互访
直接使⽤成员名
类外访问
类的数据成员和函数成员具有类作⽤域,不允许在类外的任何地⽅被访问
只有在声明了类的对象后,类对象⽤点访问符(.)访问
关于对象:
类定义是这个类的蓝图,不会分配内存
在创建类的实例(对象)时分配内存
类是⼀个类型,它的变量是对象
声明形式: 类名 对象名;
例: Clock c1,c2;
DayOfYear today;
对象所占的内存只是⽤于存放数据成员,函数成员在内存中只占⼀份复制
不能在类定义时对类的数据成员进⾏初始化,因为类是抽象的,对象才是具体的。只能通过函数成员进⾏赋值。
访问权限是相对于类⽽⾔,⽽⾮对象define的基本用法
可将赋值操作符⽤于对象
Clock c1,c2;
c1=c2;
但是,当类的数据成员是指针时会有问题
问题:
类定义时分配内存吗?
创建类的对象时分配的空间包括什么?
关于public类的数据成员和成员函数,下⾯说法对否?
只允许本类对象访问
不允许其他类的对象访问
成员函数参数表中的变量名与类的数据成员名相同时怎么区分?
类与对象(⼆)
类内数据成员不可以在声明的时候初始化。
数据成员是私有的,程序只能通过成员函数来访问数据成员。
C++要保证⼀个对象产⽣的同时必须被初始化
构造函数不可以声明为const和static,但是它的函数体内可以使⽤。
⼀般我们不要显式的调⽤构造函数。
构造函数的attention:
若构造函数带参数,在创建类对象时也带参数
如果类中没有声明构造函数,编译器会⾃动⽣成⼀个默认构造函数,这种情况下,该类的对象的初始化调⽤此默认构造函数
如果类中声明了构造函数(⽆论是否有参数),编译器便不会再为之⽣成默认构造函数
构造函数仅⽤于初始化数据成员,并进⾏其他可能需要的任何初始化操作,不要将数据的输⼊或输出操作放在构造函数中
只有把对象的值传给函数时,才会调⽤复制构造函数,如果传递引⽤,则不会调⽤复制构造函数
如果程序员没有为类声明复制初始化构造函数,则编译器⾃⼰⽣成⼀个默认复制构造函数
默认复制构造函数实现的只能是浅复制
当类的数据成员是指针类型时,浅复制会带来数据安全⽅⾯的隐患
要实现正确的复制,即深复制,必须⾃⼰编写复制构造函数
什么是浅复制,什么是深复制。
深拷贝和浅拷贝可以简单理解为:如果⼀个类拥有资源,当这个类的对象发⽣复制过程的时候,资源重
新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。
浅复制:对象p2=p1的时候,系统采⽤默认拷贝构造函数(默认的拷贝构造函数不会为新对象重新分配新的内存空间);
深复制:必须⾃⼰编写拷贝构造函数,对象p2在拷贝p1的时候获取新的内存空间。
何时调⽤:
若创建的是⾃动存储类型对象,在程序执⾏结束时调⽤
若创建的是静态存储类型对象,在程序执⾏结束时调⽤
若对象是通过new创建的,则驻留在堆栈区,当使⽤delete释放内存时调⽤
若创建的是临时对象,则在结束该对象的使⽤时调⽤
什么时候程序会调⽤构造函数?
在创建类的实例(对象)时调⽤
默认构造函数总会⾃动⽣成吗?
只要类中⾃定义了任何形式的构造函数,编译器就不会再⽣成默认的构造函数。
什么时候程序会⾃动调⽤复制构造函数?
当⽤类的⼀个对象去初始化该类的另⼀个对象时
若函数的形参为类对象,调⽤函数时,实参赋值给形参
当函数的返回值是类对象时,函数执⾏完成返回调⽤者时
何时可以使⽤类的成员函数
只有声明了类的对象后,才能使⽤成员函数
缺省的复制构造函数”采⽤“浅复制”,⽽⾮“深复制”的⽅式来实现,倘若类中含有指针变量,这两个函数注定将出错。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论