预处理器
宏定义
宏定义是最尝试用的预处理功能之一,宏定义用于将一个标识符定义为一个字符串。预处理器可以通过宏定义使程序在被编译之前将标识符替换成为定义的字符串,根据是否有参数可以将宏定义分为不带参数宏定义和带参数宏定义。
- 不带参数宏定义:#define 宏名称 字符串
#define PI 3.14
int main()
{
cout << PI << endl; //输出3.14
return 0;
}
带参数宏定义:#define 宏名称(参数1,参数2,…,参数n) 字符串
#define MAX(a, b) (a) > (b) ? (a) : (b) //宏定义并不知道会有什么参数传进来,要常带括号满足运算符优先级
int main()
{
cout << MAX(10, 20) << endl; //输出20
return 0;
}
条件编译
通常情况下,一个项目的所有代码都要参与编译,但有时因为一些原因,比如跨平台、切换版本等情况,开发者希望部分代码只在指定条件下编译,这种根据指定条件决定代码是否编译的方式称为条件编译。
例(开发过程中会有debug和release两个版本):
int main()
{
#ifdef _DEBUG //Debug为开发版本,支持调试
cout << "Debug版本" << endl;
#elif
cout << "Release版本" << endl; //Release为发布版本
#endl
return 0;
}
#运算符和##运算符
#:将宏参数转换成字符串常量
#define STR( x ) #x
int main ()
{
cout << STR(Hello world!) << endl; //输出hello world!
return 0;
}
##:用于连接两个令牌
#define CALL( n ) test##n()
void test1()
{
cout << "test1" << endl;
}
void test2()
{
cout << "test2" << endl;
}
int main ()
{
CALL(1); //调用test1
CALL(2); //调用test2
return 0;
}
预定义宏
c++中有一些编译器自带的宏,例如:
__FILE__ //表示当前文件名
__FUNCTION__ //表示当前函数
__LINE__ //表示所在行数
__DATE__ //表示编译日期
__TIME__ //表示编译时间
RTTI
C++是一种静态类型语言。其数据类型是在编译期就确定的,不能在运行时更改。然而由于面向对象程序设计中多态性的要求,C++中的指针或引用本身的类型,可能与它实际代表(指向或引用)的类型并不一致。有时我们需要将一个多态指针转换为其实际指向对象的类型,就需要知道运行时的类型信息,这就产生了运行时类型识别的要求。RTTI(Run Time Type Identification)即通过运行时类型识别,程序能够使用基类的指针或引用来检查着这些指针或引用所指的对象的实际派生类型。
类型转换
- static_cast
强制类型转换,用于替代C语言中的()强转
int a = 888888;
char b = (char)a; //C语言
char c = static_cast<char>(a); //C++
- reinterpret_cast
用于底层的强制类型转换,常用于字节数相等的转换
char *arr = new char[64];
int *p = (int *)arr; //C语言
int *p1 = reinterpret_cast<int *>(arr); //C++
- const_cast
去除const限制
const char *str = "abc";
char *p = const_cast<char *>(str);
- dynamic_cast
用于将基类指针安全的转换为派生类指针,或将指向基类的对象安全的转为派生类的引用,安全指的就是转换成功后的指针或引用一定可用。
注意事项:
- dynamic_cast只能用于含有虚函数的类
- dunamic_cast转换会检查是否可以成功转换,可以成功转换就成功转换,转换失败指针返回0,引用抛出bad_cast异常。
class A
{
public:
virtual void output() {
cout << "A" << endl;
}
};
class B :public A
{
private:
char *p;
public:
B() {
p = new char[64];
}
~B() {
if (p)
{
delete[]p;
}
}
void update() {
strcpy_s(p, 64, "ABCD");
cout << p << endl;
}
};
int main()
{
A *p = new A;
B *p1 = dynamic_cast<B *>(p);
if (p1 != nullptr)
{
p1->update();
}
else
{
cout << "null" << endl;
}
return 0;
}