zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    八. 输入输出(IO)操作2.面向字符的输入流
    八. 输入输出(IO)操作1.输入输出基本概念
    七. 多线程编程11.线程的挂起、恢复和终止
    七. 多线程编程10.线程死锁
    nginx 配置身份验证 http_auth_basic_module
    liunx mysql 备份
    8080 端口只允许内网访问配置
    nginx 配置白名单
    liunx tomcat 运行模式apr
    liunx contos 7.4 安装redis集群
  • 原文地址:https://www.cnblogs.com/denggelin/p/5617732.html
Copyright © 2011-2022 走看看