澳门威利斯人_威利斯人娱乐「手机版」

来自 澳门威利斯人 2019-07-14 08:09 的文章
当前位置: 澳门威利斯人 > 澳门威利斯人 > 正文

中的行为,四种强制类型转化

核心(Core):就是框架的主导代码,不可缺点和失误的事物,TP本人是基于MVC看法开拓的框架。
行为(Behavior) :行为在新版ThinkPHP的架构里面起注重大的效率,在系统宗旨之上,设置了相当多标签扩充位,而各种标签地点可以依次实行各自的独门行为。行为扩充就由此而诞生了,并且非常的多种类机能也是透过嵌入的行事扩张完毕的,全体行为举止扩充都以可替换和充实的,因此产生了尾部框架可组装的根基。
驱动( Driver ):数据库驱动、缓存驱动、标签库驱动和模板引擎驱动,以及外置的类扩充。

c 数据类型调换: static_cast dynamic_cast reinterpret_cast const_cast

【目录】

引言

威尼斯人注册官网,static_cast 定义

dynamic_cast 定义

举例:下行转换(把基类的指针或援引转变到子类表示)

譬喻:上行转变(把子类的指针或引用调换来基类表示)

举例: static_cast 用于着力项目之间、基本类型指针和空指针间的转换

reinterpret_cast 定义

举例:reinterpret_cast用法

const_cast 定义

举例:const_cast用法

总结

 

 

c语言中大家平常应用类似于 int a =(int)3.14等这种强制类型转变

专门的职业c 的门类调换符:static_cast 、dynamic_cast、 reindivter_cast、 const_cast, 以下分别介绍他们的用法以及举例表明

以下代码编写翻译运营意况:codeblock with gcc in win7(x64)

【1】static_cast 
用法:static_cast < type-id > ( exdivssion ) 

该运算符把exdivssion转变为type-id类型,但未有运营时类型检查来确认保证调换的安全性。它至关心注重要有如下两种用法:

①用于类档案的次序结构中基类和子类之间指针或援用的转移。

  实行上行调换(把子类的指针或援用转变到基类表示)是安枕而卧的;

  举行下行调换(把基类指针或引用转变来子类表示)时,由于未有动态类型检查,所以是不安全的。

②用来中央数据类型之间的退换,如把int调换到char,把int转变来enum。这种转移的安全性也要开辟职员来确认保证。

③把空指针调换到指标项指标空指针。

④把别的类型的表明式调换到void类型。

注意:static_cast 无法调换掉exdivssion的const、volitale、大概__unaligned属性。

msdn官方解释:

【2】dynamic_cast

用法:dynamic_cast < type-id > ( exdivssion )

该运算符把exdivssion转变到type-id类型的指标。Type-id必须是类的指针、类的引用恐怕void *;

设若type-id是类指针类型,那么exdivssion也不能够不是二个指针,要是type-id是一个援用,那么exdivssion也亟须是八个援用。

dynamic_cast重要用来类等级次序间的上行转变和下行转变,还是能用于类之间的交叉转换。

在类等级次序间张开上行转换时,dynamic_cast和static_cast 的意义是同样的;

在进展下行转变时,dynamic_cast具备类型检查的作用,比static_cast 更安全。

msdn官方解释:

 

比如:下行调换(把基类的指针或援引转变来子类表示)

亟需留心的是一旦基类中不含虚函数,dynamic_cast 下行转变编写翻译会出错

 

 1 #include<iostream> 2 using namespace std; 3  4 class father 5 { 6 public: 7     void fun1() 8     { 9         cout<<"this is father fun1 calln";10     }11     virtual void fun()12     {13         cout<<"this is father fun calln";14     }15 };16 17 class son: public father18 {19 public:20     void fun2()21     {22         cout<<"this is son fun2 calln";23     }24     void fun()25     {26         cout<<"this is the son fun calln";27     }28     int k;29 };30 31 int main()32 {33     father *pf, f;34     son *ps, s;35 36     pf = &f;// 基类的指针指向基类对象37     ps = static_cast<son *>(pf);//这种转移是不安全的,行为是不分明的38     if(ps != NULL)39     {40         ps->fun(); //在本文编写翻译意况下,实行父类的fun41         //本文编写翻译意况下,一下语句能够实行42         ps->fun2();43         ps->k = 1;44     }45     ps = dynamic_cast<son *>(pf);//转换后ps = NULL46     if(ps == NULL)47         cout<<"dynamic_cast: ps = NULLn";48     cout<<"-----------------------------------------------------------------n";49     pf = &s; //基类指针初步针对子类对象50     //此时,两种转移都以平安的51     ps = static_cast<son *>(pf);52     if(ps != NULL)53     {54         ps->fun();55         ps->fun2();56         ps->k = 1;57     }58     ps = dynamic_cast<son *>(pf);//转换后ps = NULL59     if(ps != NULL)60     {61         ps->fun();62         ps->fun2();63         ps->k = 2;64     }65 }

 

结果:

 威尼斯人注册官网 1

 

举个例子来讲:上行调换(把子类的指针或援用转变来基类表示)

 

 1 //类定义同上 2 int main() 3 { 4     father *pf, f; 5     son *ps, s; 6  7     ps = &s;// 子类的指针指向子类对象 8     //此时二种转移都是平安的 9     pf = static_cast<father *>(ps);10     if(pf != NULL)11     {12         pf->fun();13     }14     pf = dynamic_cast<father *>(ps);15     if(pf != NULL)16     {17         pf->fun();18     }19 20 }

 

 威尼斯人注册官网 2

 

举例: static_cast 用于中央类型之间、基本项目指针和空指针间的转换(无法用来中央类型指针之间调换)。

细心:基本项目由于表示数值范围的区别,因而必要用户保险调换的安全。另外dynamic_cast无法用来此类转变

 

 1 int main() 2 { 3     //基本项目间的调换,须要用户保险安全 4     int a = 一千; 5     char c = static_cast<char>(a);//不安全,1000超过了char的意味范围 6     cout<<c<<endl;//输出空 7     a = 49; 8     c = static_cast<char>(a);//安全,输出字符‘1’ 9     cout<<c<<endl;10     //c = dynamic_cast<char>(a); 错误11     cout<<"-----------------------------------------------------------------n";12     //void *和着力类型指针的调换,供给用户保险调换安全13     a = 49;14     void *pv;15     pv = &a;16     int *pi = static_cast<int *>(pv);//void * 转换为int *17     cout<<*pi<<endl; //输出4918     //pi = dynamic_cast<int *>(pv); 错误19     char *pc = static_cast<char *>(pv);//void *转char*20     cout<<*pc<<endl;//输出字符‘1’21     void *pv2 = static_cast<void *>(pc);// char * 转void *22     cout<<*((char *)pv2)<<endl;////输出字符‘1’23 }

 

 威尼斯人注册官网 3

 

 

【3】reinterpret_cast

用法:reinterpret_cast<type-id> (exdivssion)

reinterpret_cast运算符是用来拍卖非亲非故类型之间的转换;它会发出八个新的值,这一个值会有与原本参数(expressoin)有一模二样的比特位。根据reinterpret的字面意思“重新批注”,即对数据的比特位重新解释。

IBM的C 指南 里显明告诉了我们reinterpret_cast能够,恐怕说应该在什么样地方用来作为转变运算符:

  • 从指针类型到三个足足大的平头类型
  • 从整数类型恐怕枚举类型到指针类型
  • 从贰个对准函数的指针到另多少个两样类别的针对函数的指针
  • 从一个针对性对象的指针到另叁个见仁见智品种的针对对象的指针
  • 从二个针对类函数成员的指针到另多少个对准区别品类的函数成员的指针
  • 从四个指向类数据成员的指针到另贰个针对性差异档期的顺序的数据成员的指针

总计来讲:reinterpret_cast用在随意指针(或援用)类型之间的转移;以及指针与足够大的子弹头类型之间的改换;从整数类型(包罗枚举类型)到指针类型,无视大小。

注意:static_cast 无法改造掉exdivssion的const、volitale、或然__unaligned属性。

msdn官方解释:

举例:reinterpret_cast用法

 

 1 int main() 2 { 3    int a = 49; 4    int *pi = &a; 5    char *pc = reinterpret_cast<char*>(pi);//int * 到char *,用户本身安全 6    cout<<*pc<<endl; //输出字符"1" 7    unsigned long b = reinterpret_cast<unsigned long>(pc);//char * 转 unsigned long 8    cout<<b<<endl;//输出pc指向地点(即a的地方)对应的整数 9    int *pi2 = reinterpret_cast<int *>(b);//unsigned long 转 int*10    cout<<*pi2<<endl; //输出4911 }

 

 威尼斯人注册官网 4

 

【4】const_cast 

用法:const_cast<type-id> (exdivssion)

该运算符用来修改类型的const、volatile、__unaligned属性。除了const 、volatile、__unaligned修饰之外, type_id和exdivssion的类型是同样的。

常量指针被转化成特别量指针,并且依旧指向原本的目的;

常量援引被转变到极其量引用,况且照旧指向原本的指标;常量对象被转变来特别量对象。

msdn官方解释:

举例:const_cast用法

 

1 int main()2 {3    const int a = 100;4    int *b = const_cast<int *>(&a);//const int * 转int *5    cout<<*b<<endl; //输出1006    cout<<&a<<" "<<b<<endl; //两个值一样,声明b指向a的地址,只是const属性别变化了7 }

 

 威尼斯人注册官网 5

 

 

总结:

类指针或引用的上行转变static_cast 和 dynamic_cast 都可以

类指针或援引的下水调换用dynamic_cast何况决断调换后是不是为空

宗旨数据类型之间的调换用static_cast, 然则出于数值范围的两样,必要用户保证转变的安全性

未来和过去很不一致样档案的次序之间的指针或援引的转移用reinterpret_cast,它的本质是对针对内部存款和储蓄器的比特位的重解释

铲除数据的const、volatile、__unaligned属性,用const_cast

【版权注脚】转发请申明出处 

初稿地址:至于C 中虚函数表寄放地方的思辨 作者:fuliangcheng

能够明白为多个函数的指针指向了其他地方的函数。

 

若是学过C 能够用这些一个事例来证明:

    其实那是自己前一段时间思量过的四个难点,是在看《长远探求C 对象模型》那本书的时候本身产生的三个疑点,前段时间在互连网又来看类似的帖子,贴出来看看:

#include<iostream>

自家来看了众多风趣的答案,都回答的可比好,下边贴出一些有着代表性的:

using namespace std;

 

void fun_behavior_1(){

Answer 1:

  cout<<"behavior_1_body"<<endl;

威尼斯人注册官网 6

}

Answer 2:

void fun_behavior_2(){

威尼斯人注册官网 7

  cout<<"behavior_2_body"<<endl;

我们都知情,虚函数是多态机制的根底,正是在程序在运转期依照调用的靶子来剖断具体调用哪个函数,将来我们的话说它的具体贯彻原理,首要说一下笔者本人的掌握,假若有啥难堪的地点请指正
在各类包括有虚函数的类的对象的最前头(是指那几个指标目的内部存款和储蓄器布局的最前方,至于为啥是最前边,说来话长,这里就隐瞒了,首假使想念到效用难点)都有一个堪当虚函数指针(vptr)的事物指向虚函数表(vtbl),那么些虚函数表(这里仅研商最简易的单纯承袭的事态,若果是司空眼惯承袭,大概存在两个虚函数表)里面存放了那些类里面装有虚函数的指针,当大家要调用里面包车型客车函数时经过搜索那一个虚函数表来找到呼应的虚函数,那就是虚函数的兑现原理。这里笔者倘使我们都打听了,固然不打听能够去查下资料。好了,既然大家领会了虚函数的落实原理,虚函数指针vptr指向虚函数表vtbl,况且vptr又在指标的最前面,那么我们很轻松能够得到虚函数表的地址,下边小编写了一段代码测量试验了一下:

}

 

class A{

点击(此处)折叠或张开

  private:

  1. #include <iostream>
  2. #include <stdio.h>
  3. typedef void (*fun_pointer)(void);
    1. using namespace std;
  4. class Test
  5. {
  6.  public:
  7.    Test()
  8.        {
  9.      cout<<"Test()."<<endl;
  10.     }
  11.    virtual void print()
  12.        {
  13.      cout<<"Test::Virtual void print1()."<<endl;
  14.     }
  15.    virtual void print2()
  16.        {
  17.      cout<<"Test::virtual void print2()."<<endl;
  18.     }
  19. };
    1. class TestDrived:public Test
  20. {
  21.  public:
  22.  static int var;
  23.   TestDrived()
  24.     {
  25.      cout<<"TestDrived()."<<endl;
  26.     }
  27.   virtual void print()
  28.     {
  29.        cout<<"TestDrived::virtual void print1()."<<endl;
  30.     }
  31.   virtual void print2()
  32.     {
  33.     cout<<"TestDrived::virtual void print2()."<<endl;
  34.     }
  35.   void GetVtblAddress()
  36.     {
  37.          cout<<"vtbl address:"<<(int*)this<<endl;
  38.     }
  39.   void GetFirstVtblFunctionAddress()
  40.     {
  41.     cout<<"First vbtl funtion address:"<<(int*)*(int*)this 0 << endl;
  42.     }
  43.   void GetSecondVtblFunctionAddress()
  44.     {
  45.     cout<<"Second vbtl funtion address:"<<(int*)*(int*)this 1 << endl;
  46.     }
  47.   void CallFirstVtblFunction()
  48.     {
  49.     fun = (fun_pointer)* ( (int*) *(int*)this 0 );
  50.      cout<<"CallFirstVbtlFunction:"<<endl;
  51.      fun();
  52.     }
  53.   void CallSecondVtblFunction()
  54.     {
  55.     fun = (fun_pointer)* ( (int*) *(int*)this 1 );
  56.      cout<<"CallSecondVbtlFunction:"<<endl;
  57.      fun();
  58.     }
  59. private:
  60.     fun_pointer fun;
  61. };
      1. int TestDrived::var = 3;
    1. int main()
  62. {
  63.  cout<<"sizeof(int):"<<sizeof(int)<<"sizeof(int*)"<<sizeof(int*)<<endl;
  64.  fun_pointer fun = NULL;
  65.  TestDrived a;
  66.  a.GetVtblAddress();
  67.  cout<<"The var's address is:"<<&TestDrived::var<<endl;
  68.  a.GetFirstVtblFunctionAddress();
  69.  a.GetSecondVtblFunctionAddress();
  70.  a.CallFirstVtblFunction();
  71.  a.CallSecondVtblFunction();
  72.  return 0;
  73. }

  void (*behavior_1)();

这里大家通过获取虚函数表的地点调用了中间的虚函数。

  void (*behavior_2)();

目前又查了下资料,终于搞明白虚函数表vtable在Linux/Unix中寄存在可实践文件的只读数据段中(rodata),那与微软的编译器将虚函数表存放在常量段存在有的异样。将地点的文书编写翻译生成最后的可实践文件,然后使用命令:
objdump -s -x  -d a.out | c filt | grep "vtable" 能够得到以下输出

  void (*behavior_3)();

位置已经很精通了那五个类Test和TestDrived都贮存在.rodata内,至于上边那条命令,稍微解释以下,objdump能够读取
可实行文件中的详细消息,富含可实施文件的header, section, symbol等等,用objdump获得了可试行文件的标志比较多都是
咱俩看不懂的,可能说与大家源代码中的函数或然变量不太同样,那是因为C 帮助函数重载,C 对负有的暗号都做了
修饰,非常多素材称之为“函数具名”也许“符号修饰”类似的概念,然则我们要将其转移为大家源代码中的符号,那将在动用
c filt命令了,好了,到这里告一段落了,总而言之有关虚函数表的具体细节就介绍到那边。

  public:

 

  A(){

多少个值得注意的标题

    //init

  1.   虚函数表是class specific的,也正是针对性三个类来讲的,这里有一点点像三个类里面包车型大巴staic成员变量,即它是属于一个类具备指标的,不是属于某四个目的特有的,是五个类具备目标共有的。
  2.  虚函数表是编译器来选拔完成的,编写翻译器的品类差别,只怕完成格局不平等,就好像后边大家说的vptr在三个指标的最终面,不过也可能有其余达成格局,不过当下gcc 和微软的编写翻译器都以将vptr放在对象内部存款和储蓄器布局的最前头。
  3.  固然我们明白vptr指向虚函数表,那么虚函数表具体贮存在内部存款和储蓄器哪个岗位吗,就算这里我们早就能够得到虚函数表的地址。实际上虚函数指针是在构造函数执行时开端化的,而虚函数表是存放在可实施文件中的。上面包车型大巴一篇博客测量试验了微软的编写翻译器将虚函数表寄存在了对象文件或然可施行文件的常量段中,,但是本人在gcc下的汇编文件中未有找到vtbl的切实可行存放地点,重假使对可施行文件的装载和平运动作规律还一直不深切的知情,相信不久有了那个知识之后会十分轻巧的找到虚函数表到底存放在目的文件的哪二个段中。
  4. 经过测量检验,在gcc编写翻译器的贯彻中虚函数表vtable贮存在可试行文件的只读数据段.rodata中。

    behavior_1 = NULL;

参照他事他说加以考察文献:
1. 

    behavior_2 = NULL;

  1. 深度研究c 对象模型

    behavior_3 = NULL;

    //from somewhere to get the behavior_1 and behavior_2's function body.

    behavior_1 = (fun_behavior_1);

    behavior_2 = (fun_behavior_2);

本文由澳门威利斯人发布于澳门威利斯人,转载请注明出处:中的行为,四种强制类型转化

关键词: 澳门威利斯人 c++笔记