C++教程 DirectX11Frame属性

  原本打算先和大家说怎么在C++里面操作的lua的,毕竟这个Frame的主要功能便是靠lua实现的,但是想想可能有些朋友对lua不甚了解所以在说怎么和lua通信之前那么大家可以先了解lua是个什么鬼,哦,对了,我用的是5.3版本的,虽然这个版本没什么第三方库,但是现在很多常用的东西我自己已经添加好,所以顺手了也就无所谓了。

  那么今天我们从什么地方入手呢?嗯,好吧,就从“属性”这玩意而已开始吧,属性这个东西可能不是大家想想的属性,我取名字这事已经被同事吐槽了不下10次了,总觉得我名字莫名其妙,好吧,不说这些,先来认识下我所谓的属性到底是个什么鬼吧。

  假设对象A表示一个矩形,那么他将有长和宽的概念,另一个对象B表示一个椭圆,当对象A的尺寸发生变化时而对象B能够知道A的尺寸发生变化而做出相应的改变,这就是我所谓的属性的概念,长和宽是矩形的属性,属性改变将会通知关心他属性的对象所作相应的动作,现在我用代码模拟这种情况出来:

  //===================================

  class A{

  public:

  void SetValue(const MString& value){

  if(mValue == value)

  return;

  mValue = value;

  }

  private:

  MString mValue;

  };

  class B{

  public:

  void setValue(const MString& value){

  if(mValue == value)

  return;

  mValue = value;

  }

  private:

  MString mValue;

  };

  void testFun(const MString& value){

  ErrorBox("testFun called")

  }

  int main(){

  A objA;

  B objB;

  objA.SetValue(123);

  return 0;

  }

  //======================================

  现在我们要做的事就是当A类的SetValue被调用时B类的setValue也相应的被调用,也就是A的mValue的值被修改时那么B也应当修改自己的mValue值,现在我们要解决的就是该问题。

  解决该问题的方法可能有很多,如果在Qt里面我们可以考虑使用信号槽来解决,在MFC中可以考虑使用事件通知来完成,在C#里面使用事件委托来完成,嗯不过好像不论是哪一种方式感觉都不是最理想的,因为如果使用信号槽那么如果我们需要观察多个属性的话可能会要定义好多个信号,同样如果使用事件的话那么我们同样需要定义很多事件类型,所以这些都不是一个一劳永逸的方法,这都是我所认为最理想的方法。

  大家可能想起了前面我们所说的boost里面的信号槽,不错的主意,但是这个Qt的信号槽本身是差不多的东西,所以一样不满意,当然最重要的一点,如果我们通过objA调用SetValue的时候会触发objB的setValue,而objB在调用setValue的时候就会触发testFun,那么无论是Qt的信号槽还是boost的信号槽都没法做到,那么好吧,这样一来似乎没有什么选择的余地了,要么是函数对象要么就是函数指针。

  接下来要说的东西可能以我之口舌没法很好的说清楚,重要的还是大家多理解代码,我觉得一码胜千言。要让objA和objB联系起来那么必然通过一种介质,假如这个函数为Connect,那么我们先将设会是下面这种形式:

  Connect(SIGANL(objA,xxxx),SLOT(objB,xxxx));

  这个形式模仿的是Qt的connect,这就不说了,我们现在来看看如果实现这个Connect函数,而他的参数又应该是什么?想一下,当我们操作objA到时候objB会得到相应的响应,那么这个函数里面我们至少要知道objA和objB关联的到底是那个函数,所以此处应该需要将函数传递到Connnect里面。ok,现在我们来看一个原型:

  template

  void Connect(

  const MString& funName,

  void(T::*fun1)(Args...),

  T* obj1,

  std::function eventfun

  )

  从这个原型我们几乎可以肯定这就是我们所需要的了,funName是函数的名字fun1就是objA要调用的函数,obj1就是objA,eventfun即为我们被触发的函数,从这个函数原型来看他是支持无限参数的,所以他所完成的事是Qt的信号槽亦或是boost的信号都做不到的,大家也许会像何以见得呢?当然更多的可能是怎么来调用这个函数?和上面一样我们可以再进一步封装然后如下调用:

  Connect(MSIGNAL(TestA, SetValue, &objA),MSLOT(&B::setValue,&objB));

  这样一来是不是很清晰了呢?MSIGNAL包装的是类的名字,函数,对象的指针,MSLOT的参数为成员函数的地址以及对象指针,好吧,这就作为我们的调用约定,那么问题来了,MSIGNAL和MSLOT是如何实现的呢?为什么两个参数调用方式差距还如此之大呢?为了满足我们上面Connect的原型,SIGNAL必须能够生成一个和函数名等同的字符串以及该函数的函数指针和一个对象指针,而MSLOT将会通过成员函数的地址以及对象指针生成一个函数对象出来。

  看到这里大家是不是觉得开始有些懵了呢?好吧,我们正在C++的路上越走越深,因为这些如果不是出于构建库的目的话正常使用过程中几乎可能肯定不会使用得到。

  MSIGNAL和MSLOT的调用差别如此之大正是因为两者的实现方式天差地别,因为MSIGNAL的现实相当简单,其实他就是一个宏定义:

  #ifndef MSIGNAL

  #define MSIGNAL(className,memFun,obj) #memFun,&className::memFun,obj

  #endif

  但是MSLOT的实现却相当复杂,要说清楚真心不是那么容易,代码虽然不多,但是想要理清还是需要好好琢磨一下:

  //===================================

  //

  // 下面只是一些辅助函数,不需要看懂,只需要知道怎么使用MSLOT即可

  //

  template

  struct MPropertyFunHelp{

  template

  static inline auto Apply(T t,F fun,K obj, Args...args)->

  decltype(

  MPropertyFunHelp::Apply

  (

  t,fun, obj,

  std::get(t),

  args...)

  )

  {

  return MPropertyFunHelp::Apply

  (

  t,fun,obj,

  std::get(t),

  args...

  );

  }

  };

  template<>

  struct MPropertyFunHelp<0>{

  template

  static inline auto Apply(T t, F fun,K obj,Args...args)->decltype(

  std::bind(fun,obj,args...)

  )

  {

  return std::bind(fun,obj,args...);

  }

  };

  template

  struct ToFun{

  template

  static std::function Apply(T t,F fun,K obj){

  auto __t = std::tuple_cat(t,std::make_tuple(std::_Ph()));

  return ToFun::Apply

  (__t,fun,obj);

  }

  };

  template

  struct ToFun{

  template

  static std::function Apply(T t,F fun,K obj){

  return MPropertyFunHelp::Apply(t,fun,obj);

  }

  };

  //

  // 包装成员函数,我们需要用的就是下面的函数

  //

  template

  std::function MSLOT(R(T::*fun)(Args...),T* obj){

  auto t = std::make_tuple();

  return ToFun<0,sizeof...(Args),R>::Apply

  (

  t,fun,obj

  );

  }

  //

  // 包装自由函数

  //

  template

  std::function MSLOT(R(*fun)(Args...)){

  return std::forward>(fun);

  }

  //================================

  到此下面的函数便可被正确调用了:

  Connect(MSIGNAL(TestA, SetValue, &objA),MSLOT(&B::setValue,&objB));

  该调用模式适用于任何类型包括自由函数而且不受参数个数限制都是同样的调用方式,也就是说无论SetValue和setValue的参数有多少个上面的函数调用依旧不变。

时间: 2024-11-08 10:36:23

C++教程 DirectX11Frame属性的相关文章

Unity3D 学习教程 5 属性面板

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 添加一个点光源 点击添加完成 绿色的是Y轴  为高度 红色的是x轴  为横向 蓝色的是Z轴  为纵向 再看看属性 Local Rotation  x = 0  y = 3.18  z = 0  是坐标 Local Scale  x = 1  y

avalon2学习教程05属性操作

avalon2与avalon1的属性操作虽然都是使用ms-attr,但用法完全不一样. avalon1是这样操作属性的 其语法为 ms-attr-valueName="vmProp" 有多少个属性就写多个ms-attr-.其中不能省略.此外,还存在ms-title, ms-alt,ms-src, ms-href, ms-selected, ms-checked等等缩略写法.但估计很少人知道,到底哪些属性可以缩写,哪些不能. avalon2从减轻用户的记忆出发,将你要操作的属性全部打包成

SOAPUI中文教程---转移属性

Property Transfer TestSteps用于在TestSteps和它们包含的TestCase,TestSuite和Project之间传递属性.它们在许多情况下非常有用,特别是当涉及包含XML的属性时,例如 从XML消息中提取值,例如来自SOAP Response的sessionID 将值写入XML消息,例如保存的sessionID或认证数据 在属性之间传输复杂的XML内容 1. The Property-Transfer Window 创建或双击现有的Property-Transf

css基础系列教程:背景属性

作者:www.divcss.com 我们把上一节的作业的答案给大家公布一下: 1.  h1 .p1{}:表示h1标签下的所有class为p1的选择符: 2.  #content h1{}表示id为content下的所有h1标签: 3.  h1 .p1,#content h1并列关系,对class为p1的和ID为#content下的H1作用同一个效果: 4.  h1#content h2{} 表示h1下id为content标签下的h2标签,请注意这个地方不是包含没有空格而是紧接着写的.必须是属于H

Android自定义view教程03---Android 属性动画 详解

1 package com.example.donghuatest; 2 3 import android.animation.ObjectAnimator; 4 import android.animation.PropertyValuesHolder; 5 import android.animation.ValueAnimator; 6 import android.animation.ValueAnimator.AnimatorUpdateListener; 7 import andro

CSS3教程:box-sizing属性的理解border、padding与容器宽度的关系

说到 IE 的 bug,一个臭名昭著的例子是它对于“盒模型”的错误解释:在 IE5.x 以及 Quirks 模式的 IE6/7 中,将 border 与 padding 都包含在 width 之内.这为前端工程师的工作平添了不少麻烦,几户每个需要定义尺寸的 box 都要思量一下:是否触发了“盒模型 bug”? 同时,由于另一撮浏览器对标准的遵从,我们在精确定义一个在有限空间内显示的 box 时,也需要计算一下:留给它的空间只有那么大,刨去 border 和 padding,我们该把它的 widt

前端教程(9)css入门教程-css属性设置

一 字体属性 1.font-weight:文字粗细 取值 描述 normal 默认值,标准粗细 bord 粗体 border 更粗 lighter 更细 100~900 设置具体粗细,400等同于normal,而700等同于bold inherit 继承父元素字体的粗细值 2.font-style:文字风格 normal 正常,默认就是正常的 italic 倾斜 3.font-size:文字大小 fs:一般是12px或13px或14px 注意: 1.通过font-size设置文字大小一定要带单位

Vue官网教程-计算属性和监听器

<div id="app"> <p>原来:{{message}}</p> <p>逆转:{{reverseMessage}}</p> </div> <script> var vm = new Vue({ el:'#app', data:{ message:'Hello' }, computed:{ reverseMessage:function(){ return this.message.split('

IT兄弟连 HTML5教程 CSS3属性特效 文字排版

direction定义文字排列方式,所有浏览器都兼容这个属性,有两个可选值rtl和ltr.文字排版的参数说明如表1所示. 表1  CSS3文字排版参数说明 上表所示,ltr是初始值,表示left-to-right,就是从左往右的意思,具体描述就是内联内容从左往右依次排布.我们平时网页的处理都是这样的,比方说前后两个图片,默认情况下,DOM在前的就显示在左边. rtl则是另外一个值,right-to-left缩写,就是从右往左的意思,再具体描述下,就是内联内容是从右往左依次排布的,加入应用了这个C