day03 C++引用、类型转换、类的定义

来源:互联网 发布:mysql function 赋值 编辑:程序博客网 时间:2024/06/08 05:17
回顾:
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{
  //行为:进食、睡觉、玩耍..
  //属性:犬种、体重、毛色..
};
 
 
 
 
复习:类的构造函数