1 函数重载
2 缺省参数
3 哑元参数
4 inline内联函数
5 C++动态内存分配
new/new[]分配内存
delete/delete[] 释放内存
===============================
十 C++的引用(Reference)//非常重要
1 定义
引用就是别名,对引用的操作与对该变量的操作完全相同
类型 & 引用名(别名) = 变量;
1)引用定义时必须绑定一个变量,初始化以后引用的目标不能修改。
2)引用类型与绑定的变量类型必须完全相同
2 const引用(常引用)
2.1 定义引用时加const修饰,即为常引用,不能通过常引用修改引用的目标;
2.2 普通的引用只能引用左值,常引用既能引用左值也能引用右值,常引用也叫万能引用。
1)左值:可以放在赋值运算符左边的变量或表达式
注:普通的变量都是左值
2)右值:只能放在赋值运算符的右边,不能放在左边
注:常量都是右值
3 引用型函数的参数
3.1 将引用用于函数的参数,可以修改实参变量的值,可以减小函数调用的开销。
3.2 引用参数有可能意外修改实参的值,如果不希望修改实参本身,可以将形参定义为常引用,提高传参效率的同时还可以接收常量型的实参。
4 引用型函数返回值
4.1 可以将函数的返回类型声明为引用,避免函数返回值所带来的内存复制的开销;如果一个函数返回类型被声明为引用,那么该函数返回值就是一个左值;
eg:
int func(void){
static int num = 100;
return num;//返回是临时变量=num
}
int& func(void){
static int num = 100;
return num;//返回是num的别名,是左值
}
int main(void){
int res = func();//ok
cout << res << endl;//100
return 0;
}
4.2 为了避免在函数外部修改引用的目标,可以返回常引用
eg:
const int& func(void){
static int num = 100;
return num;//返回是num的别名,是左值
}
int main(void){
int res = func();//ok
//func() = 200;//error
cout << res << endl;//100
return 0;
}
4.3 不要从函数中返回局部变量的引用,因为所引用的内存会在函数返回以后被释放,但可以在函数中返回成员变量、静态变量、全局变量的引用。
5 总结引用和指针//区别
1)引用的本质就是指针,但是在C++中尽量使用引用而不是指针。
int i = 100;
int& ri = i;
int* const pi = &i;
ri 《==》 *pi
2)指针使用前可以不初始化,指向的目标也可以修改(除了指针常量);而引用定义时必须初始化,引用的目标不能修改。
eg:
int a=10,b=20;
int* p;//ok
p = &a;
p = &b;//ok
--------------
int& r;//error
int& r = a;
r = b;//不是修改引用目标而是将b值赋值给a(r)
--------------
--------------
3)可以定义指针的指针(二级指针),但是不能定义引用的指针。
eg:
int a = 10;
int* p = &a;
int** pp = &p;//二级指针,ok
------------
int& r = a;
int&* pr = &r;//error
===================
4)可以定义指针的引用,但是不能定义引用的引用
eg:
int a = 10;
int* p = &a;
int* & rp = p;//指针的引用,ok
-----------
int& r = a;
int&& rr = r;//error
int& rr = r;//不叫引用的引用,是a的另一个别名
5)可以定义指针数组,但是不能定义引用数组
eg:
int a=10,b=20,c=30;
int* parr[3] = {&a,&b,&c};//指针数组,ok
int& rarr[3] = {a,b,c};//error,不能定义引用数组
6)可以定义数组引用(定义数组的别名)
int arr[3] = {10,20,30};
int (&rarr)[3] = arr;//数组引用,ok
7)和函数指针一样,也可以定义函数引用,其语法特性和函数指针相同;
eg:
void func(int a,int b){}
int main(void){
void (*pfunc)(int,int) = func;
pfunc(10,20);
void (&rfunc)(int,int) = func;//函数引用
rfunc(10,20);
}
=======================
十一 类型转换
1 隐士类型转换
eg:
char c = 'A';
int i = c;//隐士转换
void foo(int i){...}
foo(c);//隐士转换
int func(void){
char c = 'A';
return c;//隐士转换
}
-----------------------------
2 显示类型转换
2.1 强制类型转换
char c = 'a';
int i = (int)c;//C中风格
int i = int(c);//C++风格
2.2 C++兼容C的强制转换同时,增加了四种操作符形式的类型转换
1)静态类型转换
目标类型变量 = static_cast<目标类型>(源类型变量);
使用场景:用于将void*转换为其它类型的指针
eg:
int a;
void* pv = &a;//ok
int* pa = static_cast<int*>(pv);
double d;
double* pd = &d;
int* pi = pd;//无法隐士
int* pa = static_cast<int*>(pd); //无法静态转换
2)动态类型转换(后面讲)
目标类型变量 = dynamic_cast<目标类型>(源类型变量);
3)常类型转换
目标类型变量 = const_cast<目标类型>(源类型变量);
使用场景:去除一个指针或引用的常属性
eg:
const int a = 10;
const int* pa = &a;
*pa = 20;//error
int* pa2 = const_cast<int*>(pa);//ok
*pa2=20;//ok
cout << a << endl;//20
4)重解释类型转换
目标类型变量 =
reinterpret_cast<目标类型>(源类型变量);
使用场景:
--》在任意类型指针或引用之间的转换
--》在指针和整数之间的转换
eg:0xE0200080物理地址,存放数据123;
//*((int*)0xE0200080) = 123;
int addr = 0xE0200080;
int* paddr = reinterpret_cast<int*>(addr);
*paddr = 123;
总结:
1 慎用宏,使用const、enum、inline替换
eg:
#define PAI 3.141592
==>const double PAI = 3.141592;
#define ERROR 0
#define SUCCESS 1
==>enum STATE{ERROR,SUCCESS};
#define max(a,b) ((a)>(b)?(a):(b))
==>inline int max(int a,int b){
return a > b ? a : b;
}
2 变量随用随声明,同时初始化
3 尽量使用new和delete替换malloc和free
4 少用void*,少用指针计算、少用联合体、少用强制转换
5 尽量使用string表示字符串,少用c风格char*。
=============================================
十二 类和对象(了解)
1 什么是对象
万物皆对象,任何一种事物都可以看做是对象。
2 如何描述和表达对象
通过对象的属性(名词、数量词、形容词)和行为(动词)表达对象。
eg:描述冰箱(对象)
冰箱属性:品牌、容量、颜色、功耗...
冰箱行为:冷冻、冷藏...
3 面向对象程序设计
对自然世界中对象观察引入到编程实践中的一种理念和方法,这种称为“数据抽象”,即在描述对象时,把细节东西剥离出去,只考虑一般性、有规律性、统一性的东西。
4 什么是类?
类是将多个对象的共性提取出来定义的一种新的数据类型,是对 对象的属性和行为的抽象描述,对象就是类的实例化。
eg:
现实世界 类 虚拟世界
具体对象--数据抽象--> 属性/行为--实例化--> 具体对象
struct Bingxiang{//类
string pinpai;
int rongliang;
void lengcang(){}
void lengdong(){}
};
//实例化对象、创建一个对象
Bingxiang haier;
=================
十三 类的定义和实例化
1 类的一般形式
class/struct 类名:继承表{
访问控制限定符:
//构造函数
类名(形参表)[:初始化表]{函数体}
//析构函数
~类名(void){函数体}
//成员函数
返回类型 函数名(形参表)[const]{//函数体}
//成员变量
数据类型 变量名;
};
2 访问控制限定符
public:公有成员,在类内部和外部都可以访问。
private:私有成员,只能在类的内部访问。
protected:保护成员(后面讲)
class/struct A{
public:
xxx;//公有
private:
xxx;//私有
public:
xxx;//公有
xxx;//公有
private:
xxx;//私有
};
笔试题:C++中struct 和 class关键字区别
struct定义的类默认的访问控制属性是public,而class定义的类默认的访问控制属性是private。
===================
练习:实现Dog类
class Dog{
//行为:进食、睡觉、玩耍..
//属性:犬种、体重、毛色..
};
复习:类的构造函数