《C++高级编程》之--理解C++疑难问题

第二部分、理解 C++ 疑难问题
索引:引用,const,static, extern, typedef, 类型强制转换,作用域,头文件,变长参数列表,预处理宏。
 
一、引用
1、引用
   C++引用是另外一个变量的别名(alias)。对引用的所有修改都会改变该引用所指向变量值。可以把引用看成是一种隐式指针,它可以免除获取变量地址和对指针解除引用的麻烦。
①、引用变量
   引用变量必须在创建时就初始化。
   [ 必须在分配引用时对其初始化,通常,引用是在声明时分配的,不过引用数据成员可以在包含该成员的类的初始化列表中进行初始化。]
   除非引用指向一个const值,否则不能创建指向未命名值得引用。
   int& unnamedRef = 5; // does not compile...
   const int& unnamedRef = 5 //OK
②、修改引用
   引用指向的变量在初始化之后不能再改变,只能改变这个变量的值
③、指针引用和引用指针
   可以创建指向任何类型的引用,包括 指针类型
   例: int* intP;
       int*& ptrRef = intP;
       ptrRef = new int;
       *ptrRef = 5;
  注:不能声明指向引用的引用,也不能声明引用指针(指向引用的指针)
 
 2、引用数据成员
   类的数据成员可以是引用,必须在构造函数 初始化列表中初始化引用数据成员,而不是在构造函数体中完成初始化。
 
 3、引用参数
   C++程序员不常使用独立的引用变量或者引用数据成员,最通常的用法是作为函数和方法的参数。
①、来自指针的引用
 例: int x = 5, y = 6;
      int *xp = &x, *yp = &y;
      swap(*xp, *yp); // 接收引用参数
②、传引用和传值
   传引用可以避免复制函数实参,在某些情况下会带来两个好处:
   I、效率:对象和结构体的复制会花费很长时间。
   II、正确性:不是所有的对象都允许传值,即使允许传值,也不见得就能正确的支持 深复制
 
 4、 引用返回类型
   从函数或方法也可以返回 引用(效率考虑),不是返回一个完整的对象,而是从函数或方法返回对象引用,可以避免不必要的复制。
   [ 不要返回变量( Stack 自动分配)的引用,因为函数结束时会销毁这个变量]
 
 5、 采用引用还是指针
   唯一需要使用指针的情况是,需要改变指针指向的位置,因为不能改变引用指向的变量,比如, 在动态分配内存时,就需要在指针中存储指向结果的指针,而不是在引用中存储。
 
二、关键字疑点
  1、const关键字(用于标示 变量和用于标示 方法
   ①、const变量
     其中一个用法是代替#define来声明常量,可以标示任何变量,包括全局变量和类数据成员。
   ②、const int* p; //不能改变p指向的值。
       int* const p; //把p自己声明为const。
       [int const* const p = NULL;] == [const int* const p = NULL;] //指针及其指向的值都是const。
   ③、const方法
     声明方法可以防止方法修改类中不可变的数据成员。
 
 2、 static 关键字
    ①、static数据成员和方法
      可以为类声明静态数据成员和静态方法。
    ②、static连接
       C++连接概念:
         外部连接是指,对于其他源文件,这个名字是 可用的。
         内部连接(静态连接)是指,对于其他源文件,这个名字是 不可用的。
         函数和全局变量默认都有外部连接,可以在声明前加 static,来指定 内部连接
3、 extern 关键字
   extern用来为位于它前面的名字声明外部连接,
4、函数中的static变量
   静态变量的一种用法是“记住”是否已经为一个函数完成过特定的初始化。
 
三、类型与类型强制转换
 1、 typedef
   typedef为既有的类型提一个新的名字。typedef没有创建新类型—它只是提供了引用原类型的新方法。
   类型名最常见的用法是当实际的类型名很有麻烦时可以提供一个可管理的名字,这种情况通常会在模板中发生。( STL大量使用了typedef来定义较短类型名称)
   例: typedef basic_string<char> string;
   typedef的一个巧妙之处是: 类型名可以包含作用域限定符
   例: typedef A::B C;
 
 2、 类型强制转换
   C中使用()进行强制类型转换,这种老式的转换方法在C++仍然可用的。但是C++提供了四种新的类型转换方法: static_castdynamic_castconst_castreinterpret_cast.因为C++的类型强制转换会完成更多的 类型检查,这样可以得到更好的代码。
①、 const_cast
     const_cast是最直接的类型强制转换。使用const_cast可以去除变量的常量性。
     例: const_cast<char*>(str) //template
 
②、 static_cast
   可以使用static_cast来显示地完成 C++ 语言直接支持的转换
   例: double result = static_cast<double>(i);
   static_cast的另一个用法是在 继承层次结构中完成向下类型强制转换
例: Base* b; Derived* d = new Derived();  à  d = static_cast<Derived*>b;
    Base b; Derived d; Base& br = b; Derived& dr = static_cast<Derived&>b;
 这些类型强制转换可以应用于 指针引用,但是 不能处理对象本身
 注:使用static_cast类型强制转换,不会完成运行时类型检查。要想安全地完成类型强制转换,同时进行运行时类型检查,请使用dynamic_cast。
 根据C++类型规定,任何一种 没有意义的转换static_cast都做不到。
 
③、 reinterpret_cast
   reinterpret_cast功能比static_cast更强,随之而来的是安全性较低。
   例: calss X; calss Y; X* xp; Y* yp; à xp = reinterpret_cast<X*>(yp);
   在使用reinterpret_cast时要格外小心,因为它会把 原来的位重新解释为不同的类型,而不完成任何类型检查。
 
④、 dynamic_cast
   可以使用dynamic_cast来对指针或引用进行类型强制转换,dynamic_cast会在运行时 检查底层对象的运行时类型信息。如果类型强制转换没有意义,dynamic_cast会返回NULL(对于指针转换)或者bad_cast异常(对于引用转换)。
    注意: 运行时类型信息是存储在对象的 vtable 里面的,因此,要使用 dynamic_cast ,类必须至少有一个虚函数。
    需要注意的是,可以使用static_cast或reinterpret_cast沿着继承层次结构完成同样的向下类型强制转换。他们与dynamci_cast的区别是,dynamic_cast要完成运行时(动态)类型检查。
 
3、 解析作用域
 如果不想让一个变量使用默认的作用域解析,可以使用 作用域解析操作符::
4、 头文件
 超前引用:类头文件中声明 class preference;而非#include包含。
5、C实用工具
   C++是C的超集,但是C的几个隐含特性在C++中却没有对应的替代品。
   如 变长参数列表和预处理宏
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值