C++系列笔记(七)
类型转换运算符
C++提供了一种新的类型转换运算符,专门用于基于继承的情形,这种情形在C语言编程中并不存在。4个C++转换类型如下;
- static_cast
- dynamic_cast
- reinterpret_cast
- const_cast
这4个类型转换运算符的使用语法相同:destnation_type resulr = cast_type<destination_type> (object_to_be_casted);
使用static_cast
使用static_cast可将指针向上转换为基类类型,也可向下转换为派生类型,如下面的示例代码所示:
Base* pBase=new Derived (); //constract a Derived object
Derived* pDerived=static_cast<Derived*>(pBase); //ok!
PS : 将 Derived转换为 Base被称为向上转换,无需使用任何显式类型转换运算符就能进行这种转换:
Derived objDerived;
Base* pBase = &objDerived; //ok
将 Base转换为 Derived被称为向下转换,如果不使用显式类型转换运算符,就无法进行这种转换. 除用于向上转换和向下转换外,static_cast还可在很多情况下将隐式类型转换为显式类型,以引起程序员或代码阅读人员的注意:
double dPi = 3.14159265;
int Num = static_cast<int>(dPi);
使用dynamic_cast和运行阶段类型识别
顾名思义,与静态类型转换相反,动态类型转换在运行阶段(即应用程序运行时)执行类型转换。可检查 dynamic_cast操作的结果,以判断类型转换是否成功。使用 dynamic_cast运算符的典型语法如下:
destination_type* pDest = dynamic_cast <class_type*> (pSource);
if (pDest) //check for sucess of the casting operation before using pointer
pDest->CallFunc();
实例代码如下:
#include<iostream>
#include<string>
using namespace std;
class Fish
{
public:
virtual void Swim()
{
cout << "Fish swims in water" << endl;
}
virtual ~Fish() {}
};
class Tuna:public Fish
{
public:
void Swim()
{
cout << "Tuna swims real fast in the sea" << endl;
}
void BecomeDinner()
{
cout << "Tuna become dinner in sushi" << endl;
}
};
class Carp :public Fish
{
public:
void Swim()
{
cout << "Carp swims real slow in the lake" << endl;
}
void Talk()
{
cout << "Carp talked crap" << endl;
}
};
void DetectFishType(Fish* InputFish)
{
Tuna* pIsTuna = dynamic_cast <Tuna*>(InputFish);
if (pIsTuna)
{
cout << "Detect Tuna. making Tuna Dinner:" << endl;
pIsTuna->BecomeDinner();
}
Carp* pIsCarp = dynamic_cast <Carp*>(InputFish);
if (pIsCarp)
{
cout << "Detect Carp. making Carp Talk:" << endl;
pIsCarp->Talk();
}
cout << "Verifing type using virtual Fish::Swim:" << endl;
InputFish->Swim();
}
int main()
{
Carp myLunch;
Tuna myDinner;
DetectFishType(&myDinner);
cout << endl;
DetectFishType(&myLunch);
return 0;
}
程序输出结果:
Detect Tuna. making Tuna Dinner:
Tuna become dinner in sushi
Verifing type using virtual Fish::Swim:
Tuna swims real fast in the sea
Detect Carp. making Carp Talk:
Carp talked crap
Verifing type using virtual Fish::Swim:
Carp swims real slow in the lake
使用reinterpret_cast reinterpret_cast是C++中与C风格类型转换最接近的类型转换运算符。它让程序员能够将一种对象类型转换为另一种,不管它们是否相关;也就是说,它使用如下所示的语法强制重新解释类型:
Base* pBase=new Derived ();
CUnrelated * pUnrelated = reinterpret_cast<CUnrelated*>(pBase);
这种类型转换实际上是强制编译器接受static_cast通常不允许的类型转换,通常用于低级程序(如驱动程序).注意:使用reinterpret_cast时,程序员将收到类型转换不安全(不可移植)的警告。应尽量避免在应用程序中使用 reinterpret_cast。 使用const_cast const_cast让程序员能够关闭对象的访问修饰符 const。您可能会问:为何要进行这种转换?在理想情况下,程序员将经常在正确的地方使用关键字const。不幸的是,现实世界并非如此。如下面代码所示
class SomeClass
{
public:
//……
void DisplayMembers; //a display function ought to be const
};
然而,DisplayMembers()本应为 const 的,但却没有这样定义。如果 SomeClass 归您所有,且源代码受您控制,则可对DisplayMembers()进行修改。然而,在很多情况下,它可能属于第三方库,无法对其进行修改。在这种情况下,const_cast将是您的救星。
void DisplayMembers(const SomeClass& mData)
{
mData.DisplayMembers(); //编译错误
//reason for failure:call to a non-const member using a const refernence
}
所以应该这样修改:
void DisplayMembers(const SomeClass& mData)
{
SomeClass& refData = const_cast<SomeClass&>(mData)
refData.DisplayMembers(): //Allowed!
}
除非万不得已,否则不要使用const_cast来调用非const函数。一般而言,使用const_cast来修改const对象可能导致不可预料的行为。
宏和模板简介
预处理器与编译器
定义常量
#define identifier value
使用宏避免多次包含
在预处理器看来,两个头文件彼此包含对方会导致递归问题。为避免这种问题,可结合使用宏以及预处理器编译指令#ifndef和#endif。包含<header2.h>的head1.h类似于下面这样:
#ifndef HEADER1_H_
#define HEADER1_H_
#include<header2.h>
class Class1
{
//code
};
#endif //end of header1.h
header2.h与1差不多,替换一下就可以了。预处理器首次处理header1.h并遇到#ifndef后,发现宏HEADER1_H_还未定义,因此继续处理。#ifndef后面的第一行定义了宏HEADER1_H_,确保预处理器再次处理该文件时,将在遇到包含#ifndef的第一行时结束,因为其中的条件为false。
使用define定义宏函数
典型代码:#define SQUARE(x) ((x)*(x))
宏函数经常进行简单的计算,有助于改善代码的性能。
使用assert()宏验证表达式
assert宏让您能够插入检查语句,对表达式或变量的值进行验证。要使用assert宏,需要包含<assert.h>,其语法如下:
#include<assert.h>
int main()
{
char* SayHello = new char [25];
assert(SayHello!=NULL);
//other code;
delete[] SayHello;
return 0;
}
上述代码在指针无效时可以指出来。
相关文章
- C++学习——c++逗号操作符说明(附加全部运算符优先级)
- C++项目贪吃蛇游戏笔记-项目代码
- Effective C++第17条:要在单独的语句中使用智能指针来存储由new创建的对象
- C++系列笔记(三)
- C++系列笔记(四)
- C++系列笔记(十一)
- c++实现远程开关机「建议收藏」
- 图解快速排序(C++实现)
- c++之分支语句和逻辑运算符笔记
- c++之复合类型笔记(二)
- c++ auto类型_auto C++
- C++学习笔记
- c++中constexpr_define和const定义常量的区别
- C/C++ 异或加密实现代码
- C++项目贪吃蛇游戏笔记-项目分析
- C++核心编程笔记合集
- C++常量成员函数
- c++map,mutimap删除问题分析
- C++生成dll和调用dll的方法实例
- C++Primer笔记之顺序容器的使用详解
- 浅析C++中cout的运行机制
- C++基础入门教程(九):函数指针之回调