1. 引用
1 引用的三点注意事项:1. 定义引用时一定要将其初始化成引用某个变量。
2. 初始化后,它就一直引用该变量,不会再引用别的变量了。从一而终。
3. 引用只能引用变量,不能引用常量和表达式。
2 不能通过常引用去修改其引用的内容。
int n_c = 100;
const int & r_c = n;
// r_c = 200; //编译错误。不能通过常引用去修改其引用的内容。
n_c = 300; //编译正常
3 常引用和非常引用的转换
const T & 和 T & 是不同的类型!!!
T & 类型的引用或 T 类型的变量可以用来初始化 const T & 类型的引用。
const T 类型的常变量和 const T & 类型的引用则不能用来初始化 T & 类型的引用,除非进行强制类型转换。
2. const 关键字
1 不可通过常量指针修改其指向的内容。
int n,m;
const int *p = & n;
// *p = 5; //编译出错。试图通过常量指针改变其指向的值
n = 4;
p = &m; //常量指针的指向可以改变
2 不能把常量指针赋值给非常量指针,反过来可以。
const int *p1;
int *p2;
p1 = p2; //ok
// p2 = p1; //error
p2 = (int *)p1; //ok。强制类型转换
3 函数参数为常量指针时,可避免函数内部不小心改变参数指针所指地方的内容。
void myprint(const char *p)
{
//strcpy(p,"this");
//编译出错。strcpy函数的第一个参数为 char * 类型,不能把 const char * 类型的 p 赋值给它
printf("%s",p); //ok
}
3. 动态内存分配
1 new 运算符
分配一个变量:P = new T;
T 是任意类型名,P 是类型为 T * 的指针。动态分配出大小为 sizeof(T) 字节的内存空间,并且将该内存空间的起始地址赋值给 P。比如:
int *pn;
pn = new int;
*pn = 5;
分配一个数组:P = new T[N];
T:任意类型名
P:类型为 T * 的指针
N:要分配的数组元素的个数,可以是整数也可以是表达式。
动态分配出一片大小为 N * sizeof(T) 字节的内存空间,并且将该内存空间的起始地址赋值给 P 。
int * pm;
int i = 5;
pm = new int[i*20];
pm[0] =10;
pm[100] = 30; //编译时没问题,运行时导致数组越界。0-99
new 运算符的返回类型:
new T 和 new T[N] 这两个表达式的返回类型都是 T * 。
int * p = new int;
用“new”动态分配的内存空间,一定要用“delete”运算符进行释放。
delete 指针; //该指针必须指向 new 出来的空间
int *p = new int;
*p = 5;
delete p;
delete p; //导致异常,一片空间不能被delete多次。
用 “delete” 释放动态分配的数组时要加 “[ ]” 。
delete [ ] 指针; //该指针必须指向 new 出来的数组。如果没有 [ ] 会造成 分配的动态空间没有完全释放掉。
int *p_t = new int[20];
p_t[0] = 1;
delete [] p_t;
4. 内联函数和重载函数
1 内联函数
函数调用是有时间开销的,如:参数入栈、返回值入栈,当函数非常简单且反复执行多次时,开销就会比较大。为了减少函数调用的开销,引入了内联函数机制。 编译器处理对内联函数的调用语句时,是将整个函数的代码插入到调用语句处,而不会产生调用函数的语句。缺点是编译器的可执行语句可能增多。
在函数定义前面加 “inline” 关键字,即可定义内联函数。
inline int Max(int a,int b)
{
if(a>b)
return a;
return b;
}
2 重载函数
一个或多个函数,名字相同,然而参数个数或参数类型不同,这叫做函数的重载。
以下三个函数是重载关系:
(1) int Max(double f1, double f2) { }
(2) int Max(int n1, int n2) { }
(3) int Max(int n1, int n2, int n3) { }
函数重载使得函数命名变得简单。编译器根据调用语句中的实参的个数和类型判断应该调用哪个函数。
Max(3.4, 2.5); //调用(1)
Max(2, 4); //调用(2)
Max(1, 2, 3); //调用(3)
Max(3, 2.4); //error,二定义。
若两个函数名字相同,参数个数和类型也相同,只是返回值不同,这两个函数不叫函数的重载,叫重复定义。
3 函数的缺省参数
C++中,定义函数的时候可以让最右边的连续若干个参数有缺省值,那么调用函数的时候,若相应的位置不写参数,参数就是缺省值。
void func(int x1, int x2=2, int x3=3)
{
}
func(10); //等于func(10,2,3)
func(10,8); //等于func(10,8,3)
func(10, , 8) //不行,只能最右边的连续若干个参数缺省
函数参数可缺省的目的在于提高程序的可扩充性。即如果某个写好的函数要添加新的参数,而 原先那些调用该函数的语句,未必需要使用新增的参数,那么为了避免对原先那些函数调用语句的修改,就可以使用缺省参数。
5. 类和对象的基本概念
1 C语言使用结构化程序设计
程序 = 数据结构 + 算法
程序由全局变量及众多相互调用的函数组成。
结构化程序设计的不足:1. 函数与其操作的数据结构没有直观的联系。2. 没有“封装”和“隐藏”的概念,不易差错。3. 重用。没有已有功能的重用。
2 面向对象的程序设计
面向对象的程序 = 类 + 类 + ... + 类
面向对象的程序设计方法:
将某类客观事物共同特点(属性)归纳出来,形成一个数据结构(可以用多个变量描述事物的属性);
将这类事物所能进行的行为也归纳出来,形成一个个函数,这些函数可以用来操作数据结构(这一步叫“抽象”)。(属性和操作)
然后,通过某种语法形式,将数据结构和操作该数据结构的函数“捆绑”在一起,形成一个“类”,从而使得数据结构和操作该数据结构的算法呈现出显而易见的紧密关系,这就是“封装”。(将变量和操作函数“封装”)
面向对象的程序具有“抽象”,“封装”,“继承”,“多态”四个基本特点。
对象所占用的内存空间大小等于所有成员变量的大小之和。(不考虑成员函数)
3 私有、公有、保护关键字
设置私有成员的机制叫 “隐藏” 。 “隐藏” 的目的是强制对成员变量的访问一定要通过成员函数进行,成员函数外部不能访问类的私有成员。那么以后成员变量的类型等属性修改后,只需要更改成员函数即可。否则,所有直接访问成员变量的语句都需要修改。
-
没有关键字的视为
private
class A { int a; // private int Fun(); //private public: int b; // public };
-
private
成员只能在成员函数内部访问,public
成员可以在任何地方访问 -