侯捷 more effective c++(WQ中文版) 阅读笔记1

来源:互联网 发布:linux安装eclipse 编辑:程序博客网 时间:2024/05/17 07:20
1 指针与引用的区别(指针与引用都是间接引用其他对象)
(1)操作符的不同
指针用操作符 '*'和'->'
引用用操作符 '.'
(2)两者使用环境
在任何情况下都不能使用指向空值的引用。一个引用必须总是指向某些对象。在可能将空值赋值给变量时,应该将变量声明为指针,因为可以将空值赋给指针。同时,不存在指向空值的引用意味着使用引用的代码效率比使用指针的要高。因为在使用引用之前不需要测试它的合法性。
例如:
//引用
void printDouble(const double& rd)
{
cout<<rd;//不需要测试
}
//指针
void printDouble(const double *pd)
{
if(pd)//检查是否为NULL
{
cout<<*pd;
}
}
(3)一个重要的不同是指针可以被重新赋值指向另一个不同的对象。但是引用则总是指向在初始化时被指定的对象,不能再改变。


2尽量使用C++风格的类型转换
(1)C语言语序任何类型之间进行转换
(2)C风格的类型转换在程序语句中难以识别
(3)C++引进四个新的类型转换操作符克服了C风格类型转换地缺点:static_cast/const_cast/dynamic_cast/reinterpret_cast.
原来的习惯:(type)expression
C++的习惯:static_cast<type>(expression)
例如:把int转换成double
int firstNumber,secondNumber;
double result;
原来的习惯:result = ((double)firstNumber)/secondNumber;
C++的习惯:result = static_cast<double>(firstNumber)/secondNumber;


static_cast在功能上基本上与C风格的类型转换一样强大,含义也一样。另外,static_cast不能从表达式中去除const属性。因为另一个新的类型转换操作符const_cast有这样的功能。


const_cast用于类型转换掉表达式的const或volatileness属性。例如:
class Widget{...};
class SpecialWidget:public Widget{...};
void update(SpecialWidget *psw);
SpecialWidget sw;
const SpecialWidget& csw = sw;
//错误使用
update(&csw);//csw是sw的一个引用,一个const对象,不能传递一个const SpecialWidget *变量给一个处理SpecialWidget*类型变量的函数
//正确方法(C++)
update(const_cast<SpecialWidget *>(&csw));//csw的const被显示地转换掉,csw和sw两个变量值在update中能被更新
//C强制转换
update((SpecialWidget *)&csw);
Widget *pw = new SpecialWidget;
update(pw);//错误,pw的类型是Widget*,但是update处理的是SpecialWidget*
update(const_cast<SpecialWidget *>(pw));//错误,const_cast仅能被用在影响constness or volatilness的地方上,不能用在向继承子类进行类型转换。
update(static_cast<SpecialWidget *>(pw));//正确的方法


完整的验证代码如下:
//test1.cpp
#include<iostream>
using namespace std;


class Widget
{
  int num;
public:
static int serialNum;
 
Widget()
{
   this->num = static_cast<int>(serialNum);
   serialNum ++;
  }
 
int getNum(void)
{
return this->num;
}
void setNum(int newNum)
{
this->num = newNum;
     }
};


int Widget::serialNum = 1;


class SpecialWidget:public Widget
{
string name;
public:
SpecialWidget()
{
name = "newName";
}

SpecialWidget(string newName)
{
this->name = newName;//.assign(newName);
 
}

void setName(string newName)
{
this->name = newName;
}

string getName(void)
{
return this->name;
}
};


void update(SpecialWidget *psw)
{
cout<<"There are "<<psw->serialNum<<" widgets."<<endl;
cout<<"This one is No.";
cout<<psw->getNum()<<" and its name is "<<psw->getName().c_str()<<endl;
}


int main()
{
SpecialWidget sw("aa");
const SpecialWidget& csw = sw;
//错误使用
// update(&csw);//csw是sw的一个引用,一个const对象,不能传递一个const SpecialWidget *变量给一个处理SpecialWidget*类型变量的函数
//正确方法(C++)
update(const_cast<SpecialWidget *>(&csw));//csw的const被显示地转换掉,csw和sw两个变量值在update中能被更新
// //C强制转换
// update((SpecialWidget *)&csw);
Widget *pw = new SpecialWidget;
// update(pw);//错误,pw的类型是Widget*,但是update处理的是SpecialWidget*
update(static_cast<SpecialWidget *>(pw));//错误,const_cast仅能被用在影响constness or volatilness的地方上,不能用在向继承子类进行类型转换。


getchar();
return 0;
}


dynamic_cast用于安全地沿着类的继承关系向下进行类型转换。即:用dynamic_cast把指向基类的指针或引用转换成指向其派生类或其兄弟类的指针或引用,而且你能知道转换是否成功。失败的转换将返回空指针(当对指针进行类型转化时)或者抛出异常(当对引用进行类型转换时)。dynamic_cast在帮助你浏览继承层次上是有限制的。它不能被用于缺乏虚函数的类型上,也不能用它来换掉constness。


reinterpret_cast,由于它的转换结果几乎都是执行期定义的(implementation-defined),因此使用reinterpret_cast的代码很难移植。其最普通的用途是在函数指针类型之间进行转换。例如,
typedef void (*funPtr)();


int doSomething()
{
return 1;
}


funPtr funcPtrArray[10];
funcPtrArray[0] = reinterpret_cast<funPtr>(doSomething);













原创粉丝点击