随笔-4  评论-40  文章-117  trackbacks-0


 

相对于C,C++提供了更多的额外特性:模板、运行时类型检查(RTTI)、命名空间、转型运算等,
在这里只简单介绍一下C++中的转型运算.
C++ 草案标准包含了以下四种转型运算:
static_cast
const_cast
dynamic_cast
reinterpret_cast.
这些新的操作目的是在弥补C风格的转型漏洞

转型通常用在:对象类型 表达式 函数参数 函数返回值

有些类型转换是通过C++编译器自动执行的,称为隐式转换,标准C++转换和用户自定义转换通常属于这一类
还有一些转换,必须程序员亲自干预,这一类转换称作显式转换
标准C++转换通常用在:
integral promotions (e.g., enum to int),
integral conversions (e.g., int to unsigned int),
floating point conversions (e.g., float to double),
floating-integral conversions (e.g., int to float),
arithmetic conversions (e.g., converting operands to the type of the widest operand before evaluation),
pointer conversions (e.g., derived class pointer to base class pointer),
reference conversions (e.g., derived class reference to base class reference),
and pointer-to-member conversions.
另外还有一些用户自定义的转换,比如:
你可以提供一个从X类到Y类转换的函数,参数是X,如下:
Y(const X& x)
或者是一个转换操作:
operator X()

当一个表达式需要一个不能通过阴式转换得到的类型,或者这种转换会产生歧义时,程序员必须显式表明转换的目的。

C风格转换最大的缺点在于,这种转换完全根据程序员的经验进行,转换是否成功没有提示,更可怕的是有时这种转换
会带来灾难性的后果。

C++转型运算目的在于弥补C风格转换造成的漏洞,它有如下有点:
1。语法清晰、准确甚至是有点啰嗦的语法,使得转换更容易被理解,易于发现,易于维护
2。转换目的明确,使得编译器可以轻松判断转换是否恰当
3。类型安全:允许某些运行时转换,程序员可以检查这种转型成功与否

C++提供了以下四种转型运算:
1。const_cast
从一种类型中添加或者移除const 或 volatile 性质
示例1:
void f(double& d)
{
}
void g(const double& d)
{
f(d);
}
如果在g中调用f(d)会产生变异错误,可以:
void g(const double& d)
{
f(const_cast<double&>(d));
}
示例2:

class B
{
public:
B() {}
~B() {}
void f() const;
private:
int _count;
};
在这个类中f()被声明为const,表示他告诉编译器调用这个函数不会改变对象的值,
void B::f()const
{
_count+=1; //error
}
如果我们一定要改变_count的值该怎么办呢?
void B::f() const
{
B* const localThis = const_cast<B* const>(this);
localThis->_count += 1;
}
事实上针对这种情况C++提供了一个新的关键字:mutable,用来标志那些可以被声明了const的
函数更改的成员变量,这里可以:
mutable int _count;

2。reinterpret_cast
这种转换可以在两个互不相干的类型之间进行,例如你可以将一个整数转换成一个指针,或
将一个指针转换成一个整数。

3。static_cast
静态类型转换,这是最常用的一种转换,基本上取代了C风格的转换,这种转换依赖于编译时信息,
所以被称作静态转换,例如:可以从继承类转换到基类。

4。dynamic_cast
动态类型转换,这种转换依赖于运行时信息,实际上它是RTTI的一部分。转换可能会不成功,如果不成功
返回NULL.

有关static_cast 和 dynamic_cast 的详细说明,可参阅msdn,以下我将用一个示例来说明:

示例3:
在银行系统中,假设存在两种账号:支票账号和现金帐号,他们都有存款操作,但是这两种操作是不同的。
假设他们都继承自账号类,如下:
class CAccount
{
virtual void Saveing();
}
class CPaperAccount : public CAccount
{
virtual void Saveing();
}
class CCashAccount : public CAccount
{
virtual void Saveing();
}
系统要在运行时动态的判断是哪种账号,然后调用相应的Saveing()函数,该如何处理呢?

void Save(CAccount* pAcc)
{
CPaperAccount *p1 = dynamic_cast<CPaperAccount*>(pAcc);
if(p1)
{
p1->Saveing();
}
CCashAccount *p2 = dynamic_cast<CCashAccount*>(pAcc);
if(p2)
{
p2->Saveing();
}
}
void main()
{
CCashAccount *pCashAcc = new CCashAccount();
Save(pCassAcc);
}
在save函数中不可以使用static_cast


 

 

posted on 2008-05-07 13:35 李阳 阅读(248) 评论(0)  编辑 收藏 引用 所属分类: C++

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理