当前位置: 首页 > news >正文

网站上怎么做福彩卖家建企业网站哪家好

网站上怎么做福彩卖家,建企业网站哪家好,r2网站做生存分析,百度小程序api来源#xff1a;http://www.oschina.net/translate/cpp-virtual-inheritance 来源#xff1a;http://www.cnblogs.com/BeyondAnyTime/archive/2012/06/05/2537451.html C中的虚拟继承的一些总结 1.为什么要引入虚拟继承 虚拟继承是多重继承中特有的概念。虚拟基类是为解决…来源http://www.oschina.net/translate/cpp-virtual-inheritance 来源http://www.cnblogs.com/BeyondAnyTime/archive/2012/06/05/2537451.html C中的虚拟继承的一些总结 1.为什么要引入虚拟继承 虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如:类D继承自类B1、B2而类B1、B2都继承自类A因此在类D中两次出现类A中的变量和函数。为了节省内存空间可以将B1、B2对A的继承定义为虚拟继承而A就成了虚拟基类。实现的代码如下 class A class B1:public virtual A; class B2:public virtual A; class D:public B1,public B2; 虚拟继承在一般的应用中很少用到所以也往往被忽视这也主要是因为在C中多重继承是不推荐的也并不常用而一旦离开了多重继承虚拟继承就完全失去了存在的必要。因为离开了多重继承之后虚拟继承就只会降低效率和占用更多的空间。 2.引入虚继承和直接继承会有什么区别呢 由于有了间接性和共享性两个特征所以决定了虚继承体系下的对象在访问时必然会在时间和空间上与一般情况有较大不同。 2.1时间在通过继承类对象访问虚基类对象中的成员包括数据成员和函数成员时都必须通过某种间接引用来完成这样会增加引用寻址时间就和虚函数一样其实就是调整this指针以指向虚基类对象只不过这个调整是运行时间接完成的。 2.2空间由于共享所以不必要在对象内存中保存多份虚基类子对象的拷贝这样较之多继承节省空间。虚拟继承与普通继承不同的是虚拟继承可以防止出现diamond继承时一个派生类中同时出现了两个基类的子对象。也就是说为了保证这一点在虚拟继承情况下基类子对象的布局是不同于普通继承的。因此它需要多出一个指向基类子对象的指针。 3.笔试面试中常考的C虚拟继承的知识点 第一种情况         第二种情况          第三种情况            第四种情况 class a           class a              class a              class a {              {                {                 {     virtual void func();      virtual void func();       virtual void func();        virtual void func(); };              };                  char x;              char x; class b:public virtual a   class b :public a           };                }; {              {                class b:public virtual a      class b:public a     virtual void foo();        virtual void foo();     {                 { };              };                  virtual void foo();        virtual void foo();                                };                }; 如果对这四种情况分别求sizeof(a,  sizeof(b)。结果是什么样的呢下面是输出结果在vc6.0中运行 第一种412  第二种44 第三种816 第四种88 想想这是为什么呢 因为每个存在虚函数的类都要有一个4字节的指针指向自己的虚函数表所以每种情况的类a所占的字节数应该是没有什么问题的那么类b的字节数怎么算呢看“第一种”和“第三种”情况采用的是虚继承那么这时候就要有这样的一个指针vptr_b_a这个指针叫虚类指针也是四个字节还要包括类a的字节数所以类b的字节数就求出来了。而“第二种”和“第四种”情况则不包括vptr_b_a这个指针这回应该木有问题了吧。 4.c重载、覆盖、隐藏的区别和执行方式 既然说到了继承的问题那么不妨讨论一下经常提到的重载覆盖和隐藏 4.1成员函数被重载的特征 1相同的范围在同一个类中  2函数名字相同  3参数不同  4virtual 关键字可有可无。  4.2“覆盖”是指派生类函数覆盖基类函数特征是 1不同的范围分别位于派生类与基类  2函数名字相同  3参数相同  4基类函数必须有virtual 关键字。  4.3“隐藏”是指派生类的函数屏蔽了与其同名的基类函数特征是 1如果派生类的函数与基类的函数同名但是参数不同此时不论有无virtual关键字基类的函数将被隐藏注意别与重载混淆。  2如果派生类的函数与基类的函数同名但是参数相同但是基类函数没有virtual 关键字。此时基类的函数被隐藏注意别与覆盖混淆。 小结说白了就是如果派生类和基类的函数名和参数都相同属于覆盖这是可以理解的吧完全一样当然要覆盖了如果只是函数名相同参数并不相同则属于隐藏。 4.4 三种情况怎么执行 4.4.1 重载看参数。 4.4.2 隐藏用什么就调用什么。 4.4.3 覆盖调用派生类。 多重继承 首先我们考虑一个非虚拟多重继承的相对简单的例子。看看下面的C类层次结构。 class Top { public: int a; }; class Left : public Top { public: int b; }; class Right : public Top { public: int c; }; class Bottom : public Left, public Right { public: int d; }; 使用UML图我们可以把这个层次结构表示为注意Top被继承了两次在Eiffel语言中这被称作重复继承。这意味着类型Bottom的一个实例bottom将有两个叫做a的元素分别为bottom.Left::a和bottom.Right::a。 Left、Right和Bottom在内存中是如何布局的让我们先看一个简单的例子。Left和Right拥有如下的结构 LeftTop::aLeft::b    Right    Top::a    Right::c 请注意第一个属性是从Top继承下来的。这意味着在下面两条语句后 Left* left new Left(); Top* top left; left和top指向了同一地址我们可以把Left Object当成Top Object来使用(很明显Right与此也类似)。那Bottom呢GCC的建议如下 Bottom        Left::Top::aLeft::bRight::Top::aRight::cBottom::d 如果我们提升Bottom指针会发生什么事呢 Bottom* bottom new Bottom(); Left* left bottom;这段代码工作正常。我们可以把一个Bottom的对象当作一个Left对象来使用因为两个类的内存部局是一样的。那么如果将其提升为Right呢会发生什么事 Right* right bottom; 为了执行这条语句我们需要判断指针的值以便让它指向Bottom中对应的段。 Bottom Left::Top::a Left::bright Right::Top::a Right::c Bottom::d 经过这一步我们可以像操作正常Right对象一样使用right指针访问bottom。虽然bottom与right现在指向两个不同的内存地址。出于完整性的缘故思考一下执行下面这条语句时会出现什么状况。 Top* top bottom; 是的什么也没有。这条语句是有歧义的编译器将会报错。 error: Top is an ambiguous base of Bottom 两种方式可以避免这样的歧义 Top* topL (Left*) bottom; Top* topR (Right*) bottom; 执行这两条语句后topL和left会指向同样的地址topR和right也会指向同样的地址。虚拟继承 为了避免重复继承Top我们必须虚拟继承Top class Top { public: int a; }; class Left : virtual public Top { public: int b; }; class Right : virtual public Top { public: int c; }; class Bottom : public Left, public Right { public: int d; }; 这就得到了如下的层次结构也许是你一开始就想得到的虽然从程序员的角度看这也许更加的明显和简便但从编译器的角度看这就变得非常的复杂。重新考虑下Bottom的布局其中的一个也许没有可能是 Bottom Left::Top::a Left::b Right::c Bottom::d 这个布局的优点是布局的第一部分与Left的布局重叠了这样我们就可以很容易的通过一个Left指针访问 Bottom类。可是我们怎么处理 Right* right bottom;我们将哪个地址赋给right呢? 经过这个赋值如果right是指向一个普通的Right对象我们应该就能使用 right了。但是这是不可能的Right本身的内存布局是完全不同的这样我们就无法像访问一个真正的Right对象一样来访问升级的Bottom对象。而且也没有其它简单的可以正常运作的Bottom布局。 解决办法是复杂的。我们先给出解决方案之后再来解释它。 你应该注意到了这个图中的两个地方。第一字段的顺序是完全不同的事实上差不多是相反的。第二有几个vptr指针。这些属性是由编译器根据需要自动插入的使用虚拟继承或者使用虚拟函数的时候。编译器也在构造器中插入了代码来初始化这些指针。 vptr (virtual pointers)指向一个 “虚拟表”。类的每个虚拟基类都有一个vptr指针。要想知道这个虚拟表 (vtable)是怎样运用的看看下面的C 代码。 Bottom* bottom new Bottom(); Left* left bottom; int p left-a;第二个赋值使left指向了bottom的所在地址即它指向了Bottom对象的“顶部”。我们想想最后一条赋值语句的编译情况稍微简化了 movl left, %eax # %eax left movl (%eax), %eax # %eax left.vptr.Left movl (%eax), %eax # %eax virtual base offset addl left, %eax # %eax left virtual base offset movl (%eax), %eax # %eax left.a movl %eax, p # p left.a 用语言来描述的话就是我们用left指向虚拟表并且由它获得了“虚拟基类偏移”(vbase)。这个偏移之后就加到了left然后left就用来指向Bottom对象的Top部分。从这张图你可以看到Left的虚拟基类偏移是20如果假设Bottom中的所有字段都是4个字节那么给left加上20字节将会确实指向a字段。 经过这个设置我们就可以同样的方法访问Right部分。按这样 Bottom* bottom new Bottom(); Right* right bottom; int p right-a;之后right将指向Bottom对象的合适的部位 Bottom vptr.Left Left::bright vptr.Right Right::c Bottom::d Top::a 对top的赋值现在可以编译成像前面Left同样的方式。唯一的不同就是现在的vptr是指向了虚拟表的不同部位取得的虚拟表偏移是12这完全正确确定。我们可以将其图示概括 当然这个例子的目的就是要像访问真正Right对象一样访问升级的Bottom对象。因此我们必须也要给Right和Left布局引入vptrs 现在我们就可以通过一个Right指针一点也不费事的访问Bottom对象了。不过这是付出了相当大的代价我们要引入虚拟表类需要扩展一个或更多个虚拟指针对一个对象的一个简单属性的查询现在需要两次间接的通过虚拟表即使编译器某种程度上可以减小这个代价。 向下转换 如我们所见将一个派生类的指针转换为一个父类的指针(或者说向上转换)可能涉及到给指针增添一个偏移。有人可能会想了这样向下转换反方向的就可以简单的通过减去同样的偏移来实现。确实对非虚拟继承来说是这样的。可是虚拟继承毫不奇怪的带来了另一种复杂性。 假设我们像下面这个类这样扩展继承层次。 class AnotherBottom : public Left, public Right { public: int e; int f; }; 继承层次现在看起来是这样 现在考虑一下下面的代码。 Bottom* bottom1 new Bottom(); AnotherBottom* bottom2 new AnotherBottom(); Top* top1 bottom1; Top* top2 bottom2; Left* left static_castLeft*(top1); 下图显示了Bottom和AnotherBottom的布局而且在最后一个赋值后面显示了指向top的指针。 Bottom vptr.Left Left::b vptr.Right Right::c Bottom::dtop1 Top::a AnotherBottom vptr.Left Left::b vptr.Right Right::c AnotherBottom::e AnotherBottom::ftop2 Top::a 现在考虑一下怎么去实现从top1到left的静态转换同时要想到我们并不知道top1是否指向一个Bottom类型的对象或者是指向一个AnotherBottom类型的对象。所以这办不到这个重要的偏移依赖于top1运行时的类型Bottom则20AnotherBottom则24。编译器将报错 error: cannot convert from base Top to derived type Left via virtual base Top因为我们需要运行时的信息所以应该用一个动态转换来替代实现 Left* left dynamic_castLeft*(top1);可是编译器仍然不满意 error: cannot dynamic_cast top (of type class Top*) to type class Left* (source type is not polymorphic)注polymorphic多态的 问题在于动态转换转换中使用到typeid需要top1所指向对象的运行时类型信息。但是如果你看看这张图你就会发现在top1指向的位置我们仅仅只有一个integer (a)而已。编译器没有包含指向Top的虚拟指针因为它不认为这是必需的。为了强制编译器包含进这个vptr指针我们可以给Top增加一个虚拟的析构器 class Top { public: virtual ~Top() {} int a; };这个修改需要指向Top的vptr指针。Bottom的新布局是 (当然类似的其它类也有一个新的指向Top的vptr指针)。现在编译器为动态转换插进了一个库调用 left __dynamic_cast(top1, typeinfo_for_Top, typeinfo_for_Left, -1);这个函数__dynamic_cast定义在stdc库中(相应的头文件是cxxabi.h)参数为Top的类型信息Left和Bottom(通过vptr.Top)这个转换可以执行。 (参数 -1 标示出Left和Top之间的关系现在还是未知)。更多详细资料请参考tinfo.cc 的具体实现 。 总结语 最后我们来看看一些没了结的部分。 指针的指针 这里出现了一点令人迷惑的问题但是如果你仔细思考下一的话它其实很简单。我们来看一个例子。假设使用上一节用到的类层次结构(向下类型转换).在前面的小节我们已经看到了它的结果 Bottom* b new Bottom(); Right* r b; (在将b的值赋给r之前需要将它调整8个字节从而让它指向Bottom对象的Right部分).因此我们可以合法地将一个Bottom* 赋值给一个Right*的指针。但是Bottom**和Right**又会怎样呢 Bottom** bb b; Right** rr bb; 编译器会接受这样的形式吗我们快速测试一下编译器会报错 error: invalid conversion from Bottom** to Right** 为什么呢假设编译器可以接受从bb到rr的赋值。我们可以只管的看到结果如下 因此bb和rr都指向b并且b和r指向Bottom对象的正确的章节。现在考虑当我们赋值给*rr时会发生什么(注意*rr的类型时Right*,因此这个赋值是有效的): *rr b;
http://www.pierceye.com/news/343036/

相关文章:

  • 公司网站不续费农村未来10大暴利行业
  • 代做设计网站好跨境电商排名
  • 网站备案状态查询东莞智通人才市场招聘官网
  • 做微网站要多少钱更合网站设计制作
  • 网站如何留住客户企业建设网站需要注意什么
  • 中国最受欢迎的网站网站建设要知道的
  • 软件开发公司网站模板天津网站建设方案报价
  • 做面条的网站旅游网络营销如何做
  • 知乎的网站建设和网站运营网站建设需求说明
  • 天津做陶瓷的公司网站番禺核酸检测定点医院名单
  • 教育网站赏析delphi网站开发教程
  • 电商网站设计说明书php网站服务器架设
  • 精品课程网站开发项目电子商务的分类
  • 网站建设成品动漫网站建设答辩ppt
  • 邯郸网站设计价格做网站哪便宜
  • 建设网站的一般步骤网站设计下载
  • 广东同江医院网站建设建站网站图片不显示
  • 免费在线响应式网站自助建站网站网页怎么设计
  • 池州网站建设抚顺网站建设公司
  • 网站如可引导客户义乌小程序开发制作公司
  • 环境设计排版素材网站周口市住房和城乡建设局网站
  • 建设部资质查询网站wordpress采集英文
  • 深圳北站设计方案高质量网站外链平台
  • 苏州做网站优化的公司国外 网站页面
  • 网站建设流程发布网站和网页制作鲜花网站建设论文百度文库
  • 建个人网站赚钱吗手机网站页面大小
  • php简单购物网站源码海口网红美食餐厅
  • 傻瓜式建站软件长沙做软件的公司
  • 旅行社营业网点可以做网站吗别人网站建设多少钱
  • 南宁设计网站建设教程网站建设