C++关键字

1 const

2 const_cast

3 decltype

4 default

5 delete

6 dynamic_cast

7 explicit

8 mutable

9 reinterpret_cast

10 static_cast

11 typeid

1 const

类的数据如果是const属性,需要初始化,否则报错

error C2789: “fush::d”: 必须初始化常量限定类型的对象

1 struct fushu
2 {
3     const int d;//error C2789: “fush::d”: 必须初始化常量限定类型的对象
4 };

类的函数如是是const属性,则内部不能修改数据,否则报错

error C3490: 由于正在通过常量对象访问“a”,因此无法对其进行修改

 1 struct fushu
 2 {
 3     int a;
 4     mutable int b;
 5     void showabc() const
 6     {
 7         this->a = 10;//error C3490: 由于正在通过常量对象访问“a”,因此无法对其进行修改
 8         this->b = 10;
 9     }
10 };

2 const_cast

const_cast用于去掉常量const属性

dynamic_cast用于类的多态之间的指针转换,只能用于含有虚函数的类。将多态类型向下转型dowcast为其实际类型。

reinterpret_cast用于指针的转换。

static_cast用于常规的数据类型转换。只有当类型转换有所定义,整个转换才会成功。

const_cast,用于修改类型的const或volatile属性。

const_cast<type_id> (expression)

该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。

一、常量指针被转化成非常量的指针,并且仍然指向原来的对象;

二、常量引用被转换成非常量的引用,并且仍然指向原来的对象;

三、const_cast一般用于修改底指针。如const char *p形式。

 1 #include <iostream>
 2 using namespace std;
 3 
 4 void main()
 5 {
 6     const int num = 5;
 7 
 8     int *p = const_cast<int *>(&num);//强制去掉const属性
 9     
10     *p = 4;
11 
12     std::cout << num << std::endl;//仍然是5,无法通过指针修改
13      
14     system("pause");
15 }

//const int num=10;可以修改,但是无法生效,编译的时候不读内存

//const int *p指向变量限定权限,只读不可写

//const_cast去掉常量属性

//error C3892: “p”: 不能给常量赋值

 1 #include <iostream>
 2 using namespace std;
 3 
 4 //const int num=10;可以修改,但是无法生效,编译的时候不读内存
 5 //const int *p指向变量限定权限,只读不可写
 6 //const_cast去掉常量属性
 7 
 8 void main()
 9 {
10     int num[3] = { 1,2,3 };
11 
12     const int *p = num;
13 
14     //*p = 10;//error C3892: “p”: 不能给常量赋值
15 
16     int *pnew = const_cast<int *>(p);
17 
18     *pnew = 10;
19 
20     system("pause");
21 }

3 decltype

根据一个变量,创建一个备份

 1 #include <iostream>
 2 using namespace std;
 3 
 4 void main()
 5 {
 6     double db(10.9);
 7 
 8     decltype(db) newdb(10.9);//通用备份接口,类似Java反射
 9 
10     std::cout << sizeof(newdb) << " " << newdb << std::endl;
11 
12     system("pause");
13 }

//自动数据类型,根据实际推导出类型

 1 #include <iostream>
 2 using namespace std;
 3 
 4 //自动数据类型,根据实际推导出类型
 5 
 6 template <class T1, class T2>//根据参数类型获取类型
 7 auto get(T1 data, T2 bigdata)->decltype(data*bigdata)
 8 {
 9     return data*bigdata;
10 }
11 
12 void main()
13 {
14     std::cout << typeid(get(12.0, 'A')).name() << std::endl;//double
15 
16     std::cout << get(12.0, 'A') << std::endl;//780
17 
18     std::cout << typeid(get(12, 'A')).name() << std::endl;//int
19 
20     std::cout << get(12.0, 'A') << std::endl;//780
21 
22     system("pause");
23 }

4 default

default和delete搭配使用,用于函数

5 delete

//delete可以禁用默认生成的函数

//禁用构造可以无法实例化

//禁用拷贝构造函数,可以实现禁止别人复制

//default默认存在

//error C2280: “myclassA::myclassA(const myclassA &)”: 尝试引用已删除的函数

 1 #include <iostream>
 2 
 3 //delete可以禁用默认生成的函数
 4 //禁用构造可以无法实例化
 5 //禁用拷贝构造函数,可以实现禁止别人复制
 6 //default默认存在
 7 class myclassA
 8 {
 9 public:
10     myclassA() = default;//default默认存在
11     myclassA(const myclassA &) = delete;//拷贝构造函数,delete禁用
12 };
13 
14 void main()
15 {
16     myclassA myclassa1;
17 
18     myclassA myclassa2(myclassa1);//error C2280: “myclassA::myclassA(const myclassA &)”: 尝试引用已删除的函数
19 
20     myclassA myclassa3 = myclassa1;//error C2280: “myclassA::myclassA(const myclassA &)”: 尝试引用已删除的函数
21 
22     system("pause");
23 }

6 dynamic_cast

const_cast用于去掉常量const属性

dynamic_cast用于类的多态之间的指针转换,只能用于含有虚函数的类。将多态类型向下转型dowcast为其实际类型。

reinterpret_cast用于指针的转换

static_cast用于常规的数据类型转换。只有当类型转换有所定义,整个转换才会成功。

将一个基类对象指针(或引用)cast到继承类指针,dynamic_cast会根据基类指针是否真正指向继承类指针来做相应处理

dynamic_cast <type-id> (expression)

该运算符把expression转换成type-id类型的对象。Type-id 必须是类的指针、类的引用或者void*;

如果 type-id 是类指针类型,那么expression也必须是一个指针,如果 type-id 是一个引用,那么 expression 也必须是一个引用。

面试,虚函数有虚函数表,可以确定数据类型

dynamic_cast必须要有虚函数,根据虚函数表进行转换,否则转换失败

dynamic_cast转换成功是地址,转换失败为空

类的空指针可以调用不调用数据成员的成员函数

 1 #include <iostream>
 2 
 3 //面试,虚函数有虚函数表,可以确定数据类型
 4 //dynamic_cast必须要有虚函数,根据虚函数表进行转换,否则转换失败
 5 //dynamic_cast转换成功是地址,转换失败为空
 6 //类的空指针可以调用不调用数据成员的成员函数
 7 
 8 class A
 9 {
10 public:
11     int num;
12     static int data;
13     virtual void run()//虚函数
14     {
15         std::cout << "Arun" << std::endl;
16     }
17 };
18 
19 class B :public A
20 {
21 public:
22     int num;
23     static int data;
24     virtual void run()//虚函数
25     {
26         std::cout << "Brun" << std::endl;
27     }
28     void test()
29     {
30         std::cout << "Btest" << std::endl;
31     }
32 };
33 
34 int A::data = 1;
35 int B::data = 2;
36 
37 void main()
38 {
39     A a1;
40     B b1;
41 
42     A *p1 = &a1;//直接用基类指针引用基类对象
43     A *p2 = &b1;//用基类指针引用一个派生类对象
44     B *p3(nullptr);//派生类指针,为空
45 
46     p3 = dynamic_cast<B *>(p1);
47 
48     p3->test();
49     
50     system("pause");
51 }

7 explicit

C++提供了关键字explicit,可以阻止不应该允许的经过转换构造函数进行的隐式转换的发生。声明为explicit的构造函数不能在隐式转换中使用。

//error C2440 : “初始化” : 无法从“int”转换为“classobj”

//note : class“classobj”的构造函数声明为“explicit”

 1 #include <iostream>
 2 
 3 class classobj
 4 {
 5 public:
 6     int num;
 7 public:
 8     explicit classobj(int data)
 9     {
10         this->num = data;
11         std::cout << "被构造" << std::endl;
12     }
13     ~classobj()
14     {
15 
16     }
17 };
18 
19 void main()
20 {
21     //classobj num = 5;//让人误会以为是类型转换
22 
23     //error C2440 : “初始化” : 无法从“int”转换为“classobj”
24     //note : class“classobj”的构造函数声明为“explicit”
25 
26     classobj data(5);
27 
28     system("pause");
29 }

8 mutable

mutable 可以用来指出,即使成员函数或者类变量为const,其某个成员也可以被修改。

在c++的类中, 如果一个成员函数被const 修饰,那么它将无法修改其成员变量的,但是如果这个成员变量是被mutable修饰的话,则可以修改。

e有mutable,即使成员函数为const,e仍然可以被修改

1     mutable int e = 9;
2 
3     void showabc() const
4     {
5         this->e = 10;
6         std::cout << this->a << this->b << this->c << std::endl;
7     }

9 reinterpret_cast

const_cast用于去掉常量const属性

dynamic_cast用于类的多态之间的指针转换,只能用于含有虚函数的类。将多态类型向下转型dowcast为其实际类型。

reinterpret_cast用于指针的转换

static_cast用于常规的数据类型转换。只有当类型转换有所定义,整个转换才会成功。

reinterpret_cast是C++里的强制类型转换符。

reinterpret_cast<type-id> (expression) type-id 必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,再把该整数转换成原类型的指针,还可以得到原先的指针值)。

//指针,强类型,类型决定了数据的解析方式,内存占多大

 1 #include <iostream>
 2 using namespace std;
 3 
 4 //指针,强类型,类型决定了数据的解析方式,内存占多大
 5 
 6 void main()
 7 {
 8     int num(3);
 9 
10     char *p = reinterpret_cast<char *>(&num);
11 
12     for (int i = 0; i < 4; i++)
13     {
14         printf("%c,%d,%p
", *(p + i), *(p + i), p + i);
15     }
16 
17     system("pause");
18 }

10 static_cast

const_cast用于去掉常量const属性

dynamic_cast用于类的多态之间的指针转换,只能用于含有虚函数的类。将多态类型向下转型dowcast为其实际类型。

reinterpret_cast用于指针的转换

static_cast用于常规的数据类型转换。只有当类型转换有所定义,整个转换才会成功。

float x = 10.1f;
std::cout << static_cast<int>(x) << std::endl;//由float转换到int有所定义

f(static_cast<std::string>("hello world!"));//由char *转换到string有所定义

该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。

static_cast < type-id > ( expression )

 1 #include <iostream>
 2 using namespace std;
 3 
 4 void main()
 5 {
 6     int n = static_cast<int>(78.98);
 7 
 8     std::cout << n << std::endl;//78
 9     
10     int *p = static_cast<int *>(malloc(100));
11 
12     system("pause");
13 }

11 typeid

在C++中,typeid用于返回指针或引用所指对象的实际类型。

 1 #include <iostream>
 2 using namespace std;
 3 
 4 void main()
 5 {
 6     double db(10.9);
 7     double *pdb(&db);
 8 
 9     auto num(pdb);//通用传入接口
10 
11     std::cout << typeid(db).name() << std::endl;//double
12     std::cout << typeid(pdb).name() << std::endl;//double *
13     std::cout << typeid(num).name() << std::endl;//double *
14 
15     system("pause");
16 }

typeid是根据指针检查类型的,如果类中没有虚函数,那么可能会检测不准确

1类中没有虚函数,检测不准确

直接用基类指针引用基类对象

用基类指针引用一个派生类对象

 1 #include <iostream>
 2 
 3 //typeid是根据指针检查类型的,如果类中没有虚函数,那么可能会检测不准确
 4 
 5 class A
 6 {
 7 public:
 8     int num;
 9     static int data;
10     void run()
11     {
12         std::cout << "Arun" << std::endl;
13     }
14 };
15 
16 class B :public A
17 {
18 public:
19     int num;
20     static int data;
21     void run()
22     {
23         std::cout << "Brun" << std::endl;
24     }
25     void test()
26     {
27         std::cout << "Btest" << std::endl;
28     }
29 };
30 
31 int A::data = 1;
32 int B::data = 2;
33 
34 void main()
35 {
36     A *p1 = new A;//直接用基类指针引用基类对象
37     A *p2 = new B;//用基类指针引用一个派生类对象
38     
39     std::cout << typeid(p1).name() << " " << typeid(p2).name() << std::endl;//检查两个指针类型
40 
41     std::cout << typeid(*p1).name() << " " << typeid(*p2).name() << std::endl;//检查两个指针指向的类型,实际上是不一样的,但是检测不准确
42 
43     std::cout << (typeid(p1) == typeid(p2)) << std::endl;//1,检查两个指针类型
44 
45     std::cout << (typeid(*p1) == typeid(*p2)) << std::endl;//1,检查两个指针指向的类型,实际上是不一样的,但是检测不准确
46 
47     system("pause");
48 }

2类中有虚函数,检测准确

直接用基类指针引用基类对象

用基类指针引用一个派生类对象

 1 #include <iostream>
 2 
 3 //typeid是根据指针检查类型的,如果类中没有虚函数,那么可能会检测不准确
 4 
 5 class A
 6 {
 7 public:
 8     int num;
 9     static int data;
10     virtual void run()//虚函数
11     {
12         std::cout << "Arun" << std::endl;
13     }
14 };
15 
16 class B :public A
17 {
18 public:
19     int num;
20     static int data;
21     virtual void run()//虚函数
22     {
23         std::cout << "Brun" << std::endl;
24     }
25     void test()
26     {
27         std::cout << "Btest" << std::endl;
28     }
29 };
30 
31 int A::data = 1;
32 int B::data = 2;
33 
34 void main()
35 {
36     A *p1 = new A;//直接用基类指针引用基类对象
37     A *p2 = new B;//用基类指针引用一个派生类对象
38     
39     std::cout << typeid(p1).name() << " " << typeid(p2).name() << std::endl;//检查两个指针类型
40 
41     std::cout << typeid(*p1).name() << " " << typeid(*p2).name() << std::endl;//检查两个指针指向的类型
42 
43     std::cout << (typeid(p1) == typeid(p2)) << std::endl;//1,检查两个指针类型
44 
45     std::cout << (typeid(*p1) == typeid(*p2)) << std::endl;//0,检查两个指针指向的类型
46 
47     system("pause");
48 }
原文地址:https://www.cnblogs.com/denggelin/p/5617732.html