精华内容
下载资源
问答
  • 曾经优秀的人,怎么就突然不优秀了。

    万次阅读 多人点赞 2020-01-07 18:00:00
    职场上有很多辛酸事,很多合伙人出局的故事,很多技术骨干被裁员的故事。说来模板都类似,曾经是名校毕业,曾经是优秀员工,曾经被领导表扬,曾经业绩突出,然而突然一天,因为种种原因,被裁员了,...

    职场上有很多辛酸事,很多合伙人出局的故事,很多技术骨干被裁员的故事。说来模板都类似,曾经是名校毕业,曾经是优秀员工,曾经被领导表扬,曾经业绩突出,然而突然有一天,因为种种原因,被裁员了,想申诉,想求解释,结论是,能力不匹配,未能与企业一起成长云云。明明曾经优秀,怎么就突然不优秀了,拖后腿了呢。

    这有两说,一说是企业冷血,卸磨杀驴,嫌弃老人成本太高,又没有年轻人肯卖命;另一说是,一些老白兔们不知道追求进步,躺在功劳本上坐吃山空,还占着位置阻碍了新人的前进。那么根据不同人的屁股位置,会有不同的选择。

    你猜我站哪一边?

    我不站立场,我只站事实,事实只有一句话,优秀的门槛越来越高。

    把时间拉长了说,解放前能识字的人才多少,高等小学毕业的就算是文化人了。三十年前上大学是个什么概念,家族之光。现在呢,每年考研人数跟我们当年高考人数差不多,研究生录取人数也跟我们当年高考录取人数差不多。

    那只说最近这些年,只说我们行业相关的。

    三十年前,中国能熟练操作电脑的人有多少,机房都要做防尘,操作者带着手套去操作键盘,会五笔输入法会排版就很厉害了,那时候新上大学的很多学生,看到电脑战战兢兢都不敢乱碰,生怕碰坏了赔不起。当时写文档排版还是有点小复杂的。

    二十年前,中国会写程序的有多少人,能做交互网页设计,能写SQL,就足够找一份不错的饭碗。如果还知道防范SQL注入和跨站脚本,会一些数据库索引优化,绝对可以被称为高手。那时候的高手门槛就是这么低。

    十年前呢?今天呢?

    因缘际会,我跟国内很多40岁左右的技术大咖关系密切。很多大咖私下都说过类似的话,如果用现在他们的技术面试题去考核当年入职的他们,根本过不了面试。

    一代更比一代强,是历史的必然,但这又意味着什么?

    1、我们都站在巨人的肩膀上。

    当年牛顿说,他站在巨人的肩膀上,那么爱因斯坦呢,站在牛顿的肩膀上,每一代的经验和技术积累传承,历史天才们的发现,很多都是现在中学生的课本内容。新的算法思想,新的技术工具,层出不穷。

    2、学习资源和学习工具更加强大。

    搜索引擎,便利的在线教程,各种电子文档,各种论文查询。这以前怎么比。真没法比。

    3、竞争态势的压迫。

    我说我小时候是散养的,我们那一代基本都是散养的,也就是家长基本没怎么管过,小学就在家门口,什么名校不名校,有学上就行了,其他的一切靠自己。那时候哪有什么所谓k12教育产业,家长普遍都穷,第三方教育机构基本不存在的。

    现在可不一样,从学区房的竞争开始,我跟我大学同学聊天,他们几乎各个都买了学区房,各个都是从小给孩子报各种班,我说你们这帮学霸当年谁是学区房出来的,当年谁从幼儿园小学家里就报班的,站出来我看看,人家说,时代不同了,还真是时代不同了。

    大家都散养的时候,你自觉努力就出类拔萃了;但大家都巨资投入教育资源培养的时候,单纯靠自觉努力,再想出类拔萃,就相当难了。

    为什么优秀的人突然不优秀了,因为优秀的门槛一直在变高,因为每年都在重新定义优秀的标准,这次还真是重新定义。

    以前很多围棋爱好者一直争论一个话题,历史上那些大名鼎鼎的围棋国手,那些如雷贯耳的围棋高手,放在现在,是什么水平。

    坦白说,如果那些高手直接穿越过来,不可能下的过顶尖职业棋手,让2子我觉得都难获一胜,业余顶尖棋手我觉得他们都很难下得过。是说他们不够优秀么?

    现在的经验技术总结,现在的顶尖棋手竞争氛围,现在的顶级职业棋谱的广泛传播,现在的围棋AI工具,那时候统统没有,不说跟古人比,就算是今天的柯洁去比三年前的柯洁,我觉得让个先都没问题,为什么,因为围棋AI的广泛使用,短短两年多时间里,很多围棋开局优劣的判断和分析思路已经发生了重大革命,和旧定势思路相比,开局几十手棋下完,让先优势就抹平了。

    但是不是说历史上高手都不行呢?如果他们很年轻就穿越过来,跟现在的职业棋手一起训练,一起学习,学习几年之后,你再问鹿死谁手,那就难说了,甚至我会认为历史高手可能会进步得更快,因为他们在那样的环境下都能下的足够好。

    但问题是,每个人都只能年轻一次,当我们不再年轻的时候,看到新崛起的优秀的年轻人,力不从心,真的力不从心。聂卫平老师,曹薰铉老师,小林光一老师他们也都看到了围棋AI和新的围棋思想,你说他们还有可能再战胜柯洁了么?毕竟斗不过岁月无情。

    岁月无情,那我们怎么应对?

    1、尽量让自己拥有较长时间竞争力的技能和思想。

    比如说,很多年轻人热衷于学习新的工具,新的编程语言,学习在新的平台做系统,当然,这是有一定红利期的,但作为个人的竞争力,稍过几年,很可能就一文不值。

    我应该是中国最早写cold fusion代码的人,谁还知道这是啥玩意,是中国最早翻译asp教程的人,也是中国最早一波写php代码的人,从当时看,很牛逼对不对,过不了几年,这玩意也算竞争力?

    什么是竞争力,多理解系统底层的逻辑和思想,诸如内存分配的机制,多理解数据结构的原理和设计理念,这些也不能说永远都有竞争力,但如果理解到位,并且应用得当,至少可以保证二三十年自己的思想不会在业内落伍。

    具有发现问题的敏锐度,掌握分析问题的方法和思路,也能让自己职场竞争力相对牢固一些。

    那些中年技术大咖,你让他们继续跟年轻人一起比敲代码,真敲不过,当然个别有还能敲得很利索的,大部分可能已经无法熟练的使用具体的编程工具和具体的特定算法,跟优秀的年轻人比拼了,但他们知道如何有效的在复杂的系统中发现问题,定位问题,并针对性的给出解决问题的方向,这就是竞争力,这个竞争力,依然可以持续很多年。

    2、站的越高,位置越稳。

    如果你曾经站在Top 1/1000的优势位置,虽然来了很多优秀的年轻人,你可能力不从心,掉到了Top 1/100。虽然没有曾经的光辉,但仍然具有足够的竞争力。仍然配得上非常优秀的标签。

    如果你沾沾自喜自己现在属于Top 20%的优秀人群,但年轻人一波波冲进来,你眼看着自己掉到了 Top30%,  Top40%, Top50%,对不起,优秀俩字从此与你无缘。

    3、即便力不从心,也要奋力向前。

    你说一代更比一代强,有的时候真的力不从心,但看你目标是什么,想独孤求败,一览众山小,可能越来越难。但毕竟!毕竟大部分人是懒惰,缺乏耐心的。想让自己超过大多数人,毕竟没那么难。

    TK教主有句话很经典,具体原文找不到了,大概意思我整理一下,如果你否定天分的存在,只强调勤奋努力,那就是蠢。但如果你因此认为勤奋努力没有用,那就是又懒又蠢。

    比如我这些年一直下围棋,学习新的定势,不断提升棋力,实话说,以我的水平,你说打职业比赛,开玩笑,差距太大了。每年会有大量学棋青少年超过我的水平,这是挡不住的,认了,但只要我坚持进步,就会超过很多停步不前的围棋爱好者,我四十多岁,还在涨棋,没有年轻人学的快是真的,但总有大量停步不前的围棋爱好者会被我超越对不对。

    只要你肯进步,总会超越大量不进步的人。对于普通人来说,这就足够了。

    4、广结善缘,稳固地位。

    趁着自己优秀的时候,多帮助和扶植优秀的年轻人,我一直是这么强调的,等他们足够优秀了,你的地位和影响力会越加稳固。

    有些人觉得,教会徒弟,饿死师傅。干嘛不给自己留点竞争力。

    现在这个社会,优秀的人才太多,优秀的年轻人太多,你不教,别人也会教,你的徒弟不抢你的饭碗,别人的徒弟也会抢你的饭碗。你结善缘,还能等他们成长起来感恩回馈,你藏着掖着,最后你真的以为能守住什么竞争力?抢你饭碗的年轻人会在任何角落里冒出来。

    5、提升视野,向上发展。

    一个人在职场如果经历了很多事情,经历了很多岁月,多半总会有点优势,这个优势叫做见识,你知道一个企业是怎么成,怎么败的,你知道一个产品是怎么做起来,怎么壮大的。这就是你的竞争优势,年轻人学的算法再好,很多想法再优秀,没有见识过大场面,总会缺那么一点格局和视野。

    但可怕的是,很多人虽然经历了很多事,却没有见识,匮乏视野。

    比如简单化,标签化的看待问题,老板当时成功是因为运气比较好。

    比如从不关心产业和市场变化的情况,一直随波逐流。

    比如在自己的工作职能之外,毫不关心合作伙伴,上下游,同行的生存和发展话题。

    当然也比如更常见的,只关心行业八卦话题,对各种巨头老板的绯闻八卦如数家珍,对各种真真假假的小道消息乐此不彼。并以为这是见识,视野。

    所以,当更有活力,更便宜的年轻人冲上来,他们的教育背景比你更好,他们的算法逻辑比你更清晰,你还剩下什么,信谣传谣的能力和素质?

    还想安安静静当个螺丝钉?对不起,你生锈了。

    总结一下,优秀的门槛越来越高,这是历史趋势,谁也挡不住。

    但任何时代,大部分人总是会固步自封,随波逐流,随着岁数增长,你可能真的无法挡住优秀的年轻人超越你,但你只要肯进步,总会不断超越那些停步不前的大多数。

    另外就是广结善缘,提升格局,不要让自己停留在跟年轻人竞争基本战斗能力的场景里,那样你就很难维持竞争力了。

    政治正确的说法是,无论岁数多大,总能坚持学习和进步,保持在领域之巅,实话说,总有这样的实例告诉你,牛人可以展示出跨越时代的能力和素质,但,对大部分人来说,随着岁数增长,精力,注意力,记忆力,体力都会逐渐衰退,这是不可避免的。你不能指望现在的姚明去打nba,也不能指望现在的聂卫平去战胜柯洁。尽管他们曾经都是巅峰存在。

    但现在的姚明可以当篮协主席,现在的聂卫平可以搞围棋培训。利用曾经的优势,转换赛道,用见识和格局作为竞争力,一样大有可为。


    现在很多优秀的年轻人,技术水平超越我太多了,我去跟他们拼代码?拼刷题?拼算法?绝对的自取其辱。但为什么他们还都很尊重我,很愿意聆听我对他们职场的建议,其实同理。

    题图,英雄迟暮,壮志未已

    展开全文
  • 当前一家饮料店,里面卖着很多饮料 设计如下 问题描述 这里箭头符号表示BeverageStore依赖Juice,及高层依赖于低层 在BeverageStore中,对应的是具体的饮料实现,具体代码如下 pa...

    依赖倒置原则定义

    如下(可先不管)
    - 高层模块不应该依赖低层模块,两者都应该依赖抽象
    - 抽象不应该依赖细节
    - 细节应该依赖抽象

    情景描述

    当前有一家饮料店,里面卖着很多饮料

    设计如下
    这里写图片描述

    问题描述

    1. 这里箭头符号表示BeverageStore依赖Juice,及高层依赖于低层
    2. 在BeverageStore中,对应的是具体的饮料实现,具体代码如下
    package headfirst.hd.dep;
    
    public class BeverageStore {
    
        //卖果汁
        public Juice saleBeverage() {
            //果汁的具体实现
            Juice juice = new Juice();
            return juice;
        }
    }
    

    修改设计,为饮料提供统一接口

    备注:这是网上很多教程讲的例子,根据我自己的理解,这不是依赖倒置的体现,后来我会给出原因

    这里写图片描述
    核心代码变为一下代码,依赖变为不仅依赖低层组件的实现,而且还依赖低层组件的抽象,比之前还更糟糕

    package headfirst.hd.dep;
    
    public class BeverageStore {
    
        //卖果汁
        public Beverage saleBeverage() {
            //果汁的具体实现
            Beverage beverage = new Juice();
            return beverage;
        }
    }
    

    对这个代码再优化一下

    package headfirst.hd.dep;
    
    //这是网上最常见方式
    public class BeverageStore {
        //卖果汁
        public Beverage saleBeverage(Beverage beverage) {
            //做一些其他操作
            return beverage;
        }
    }
    

    客户端Client

    package headfirst.hd.dep;
    
    public class Client {
    
        public static void main(String[] args) {
            BeverageStore store = new BeverageStore();
            store.saleBeverage(new Juice());
    
        }
    
    }

    对应设计变化为
    这里写图片描述

    1. 高层依赖低层还是曾在,并且由更高层依赖了低层模块
    2. 我个人觉得这应该叫依赖转移

    引入工厂方法模式改进以上例子

    工厂模式设计图

    这里写图片描述

    核心代码
    BeverageStore

    package headfirst.hd.dep;
    
    //工厂方法模式
    public abstract class BeverageStore {
        //卖果汁
        public Beverage saleBeverage() {
            //直接使用自身定义的抽象方法
            Beverage beverage = createBeverage();
            //做一些其他操作
            return beverage;
        }
    
        /**
         * 抽象类BeverageStore抽象方法定义,Beverage createBeverage()
         * 表明createBeverage与BeverageStore为一体,关系为一根横线,
         * 两者没有实质依赖关系,因为在BeverageStore中,直接使用自身
         * 定义方法createBeverage,在类BeverageStore的其他方法中,
         * 直接使用该类型,具体实现具体类,延迟到子类
         */
        abstract Beverage createBeverage();
    }
    

    BeverageStoreFactory

    package headfirst.hd.dep;
    
    //工厂方法模式
    public class BeverageStoreFactory extends BeverageStore{
    
        @Override
        Beverage createBeverage() {
            //可传入参数,得到更多实例,
            //或者BeverageStoreFactory2,多个工厂方法,都可以
            return new Juice();
        }
    }
    

    测试Client

    package headfirst.hd.dep;
    
    public class Client {
        //优秀啦,一点都没有低层模块代码
        public static void main(String[] args) {
            BeverageStore store = new BeverageStoreFactory();
            store.saleBeverage();
        }
    
    }
    

    理解加入模式前后的不同

    加入前
    这里写图片描述
    加入后
    这里写图片描述

    主要区别体现在两点

    1. store与product关系
      加入工厂前,实际上还是具有依赖关系,实质上将依赖关系往更高层转移
    package headfirst.hd.dep;
    
    //这是网上最常见方式
    public class BeverageStore {
        //卖果汁
        public Beverage saleBeverage(Beverage beverage) {
            //做一些其他操作
            return beverage;
        }
    }
    

    加入工厂后

    //工厂方法模式
    public abstract class BeverageStore {
        //卖果汁
        public Beverage saleBeverage() {
            //直接使用自身定义的抽象方法
            Beverage beverage = createBeverage();
            //做一些其他操作
            return beverage;
        }
    
        /**
         * 抽象类BeverageStore抽象方法定义,Beverage createBeverage()
         * 表明createBeverage与BeverageStore为一体,关系为一根横线,
         * 两者没有实质依赖关系,因为在BeverageStore中,直接使用自身
         * 定义方法createBeverage,在类BeverageStore的其他方法中,
         * 直接使用该类型,具体实现具体类,延迟到子类
         */
        abstract Beverage createBeverage();
    }

    所有加入前还是具有依赖关系,所以是箭头,加入工厂模式之后,为接口定义,为一体,所以属于直线
    2. storefactory取代了Client位置
    加入前层级关系
    这里写图片描述
    加入后层级关系
    这里写图片描述

    倒置的两种理解

    第一种,从设计上理解

    这里写图片描述

    如果所示,正常都是高层调用低层,简单推理一下

    1. product1(具体的实现)依赖于product(抽象)
    2. 由于引入工厂模式后,store与product为同一关系(同时存在)
    3. 推理出,product1(具体的实现)依赖于store

    因此,形成了依赖倒置的现象

    第二种,从思想上理解

    没有引入工厂方法模式之前,我们需要一杯果汁(Juice),我们的思路时候这样的

    先有一个饮料店(BeverageStore),然后才会有果汁(Juice),简单的说就是先有饮料店,最后决定卖什么饮料

    引入工厂方法模式之前,我们需要一杯果汁(Juice),我们的思路时候这样的
    这里写图片描述

    先定义饮料接口,后实现具体的饮料店,这些我们可以理解为,我们先选择什么要的饮料,最后决定开什么样的饮料店

    因此,形成了依赖倒置的现象

    展开全文
  • 优秀到卓越

    万次阅读 多人点赞 2020-12-31 12:14:32
    卓越作为我们公司的企业文化,更应该是一 “虽不能至,然心向往之”,只要能够用心做好每一件事情,从为他人、为公司着想的角度思考、做一点。那么不管是艰巨的任务还是日常事务,我们都能做出卓越的贡献。这...

    目录

    卓越的定义

    卓越就是比优秀更优秀。

    卓越是一个高尚的品格,它包括了:责任心、专业水平、高标准。我们很难要求每个人都能实现真正的卓越。卓越作为我们公司的企业文化,更应该是一种 “虽不能至,然心向往之”,只要能够用心做好每一件事情,从为他人、为公司着想的角度多思考、多做一点。那么不管是艰巨的任务还是日常事务,我们都能做出卓越的贡献。这是一种个人对美好的追求,是一种成就感。

    1. 个人层面:专业地做事,比如代码逻辑清晰,易于理解。文档清晰,软件工程符合公司规范。
    2. 团队层面:努力促进团队进步,在专业地做好自己事情的同时,为团队贡献智慧。无论是业务方面,还是团队建设方面。要帮助同事成就自我,和团队一起进步。
    3. 公司层面:打造铁打的营盘,塑造整体竞争力。一个人成长是好,团队成长更好,整个公司成长才是最好。做好业务能力开放,移交,不要全权代理。争取公司整体所有团队在业务能力上一起进步。

    行动准则

    1. 面对工作:要从他人的角度、可移交的角度出发进行思考和完成任务。
    2. 面对协作:个体和互动,要高于流程和形式。
    3. 面对市场:响应变化高于循规蹈矩。
    • 不以自我为中心,始终追求团队的共同成长。

      • 强调 Redmine 的管理记录,要求工作内容可移交、可追溯、可沉淀、可普惠于所有研发同事。而不仅仅是自己完成。
      • 鼓励自发的技术分享交流,让知识不仅仅停留于自己的脑袋或博客,而是可以内部开源给所有同事,共同成长。
    • 不以部门为界限,始终追求跨部门的信息同步与协作。

      • 5G + 边缘计算是一门较前沿的学科,研发部门作为技术攻关部门,有责任、有义务为公司所有部门的同事进行技术科普、分享、培训。
      • 研发部门要往前冲,支持销售、售前兄弟用技术引导客户、征服客户,在客户面前用心去感受客户的需求,而不仅仅是依赖前端同事的输入;支持运开兄弟在关键实施时刻 “扶一把” 上马。
    • 不以工作为唯一目的,把公司当作第二个家。

      • 积极组建、参与户外活动,在活动中培养感情,加深理解。养成活跃的主人翁精神面貌。

    从优秀到卓越

    《从优秀到卓越》— 吉姆·柯林斯,真正卓越的公司会有一些共同的特征:1)强调纪律的文化;2)强调飞轮理念。

    • 强调纪律的文化

      • 拥有杰出的领导:不以自我为中心,把公司利益摆在第一位,通过组织形成一个强大的团队。
      • 正确的价值观念:领导营造的企业文化是组织目的、目标、体系以个人自由和责任为基础的框架下建立起来的。
      • 合适的人适当的工作:实现跨越的公司领导会寻找自律又具备能够适应公司文化特有的价值观的人。
      • 了解路在何方:实现跨越的公司其成功是建立在对公司的三个主要方面的深刻理解上,即它们在什么方面成为世界上最优秀的,对什么充满热情,是什么驱动公司的经济引擎。
    • 强调飞轮理念:

      • 公司实现从优秀到卓越的飞跃不是一蹴而就的,而要经历一系列的突破,正如沿着一个方向转动巨大的一个轮子,飞轮一周周地旋转直到发生突破而得到最大动能。

    组织文化是一个组织所有成员所共享的,并且作为标准传承给新成员的,一系列价值观、信念、看法和思维方式的总和。它不被诉诸文字,但却体现在组织中每一个人的每一个行为当中。

    展开全文
  • 深入理解UE4宏定义—— GENERATED_BODY

    万次阅读 2017-06-01 18:37:40
    在前几年的写引擎的时候,也类似使用过这些宏定义的方法,用法也是比较复杂的。现在就借UE4来回顾和分析一下。 测试版本:4.15 看例子:// Fill out your copyright notice in the Descript


    本文章由cartzhang编写,转载请注明出处。 所有权利保留。
    文章链接:http://blog.csdn.net/cartzhang/article/details/72834164
    作者:cartzhang

    一、GENERATED_BODY 都实现了什么?


    在前几年的写引擎代码的时候,也类似使用过这些宏定义的方法,用法也是比较复杂的。现在就借UE4来回顾和分析一下。

    测试版本:4.15
    看例子:

    // Fill out your copyright notice in the Description page of Project Settings.
    
    #pragma once
    
    #include "GameFramework/PawnMovementComponent.h"
    #include "CollidingPawnMovementComponent.generated.h"
    
    /**
     * 
     */
    UCLASS()
    class HOWTO_AUTOCAMERA_API UCollidingPawnMovementComponent : public UPawnMovementComponent
    {
        GENERATED_BODY()
    
    public:
        virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override;
    
    };
    

    直接F12导航到 定义:
    在ObjectMarcro.h 中的613行,里面还有其他的,比方说之前版本的遗留解决方案。

    重点就这几行:

    
    // This pair of macros is used to help implement GENERATED_BODY() and GENERATED_USTRUCT_BODY()
    #define BODY_MACRO_COMBINE_INNER(A,B,C,D) A##B##C##D
    #define BODY_MACRO_COMBINE(A,B,C,D) BODY_MACRO_COMBINE_INNER(A,B,C,D)
    
    #define GENERATED_BODY_LEGACY(...) BODY_MACRO_COMBINE(CURRENT_FILE_ID,_,__LINE__,_GENERATED_BODY_LEGACY)
    #define GENERATED_BODY(...) BODY_MACRO_COMBINE(CURRENT_FILE_ID,_,__LINE__,_GENERATED_BODY)


    GENERATED_BODY ————> BODY_MACRO_COMBINE ————> BODY_MACRO_COMBINE_INNER————>A##B##C##D

    这里需要注意的是,## 在C++宏定义中,这里表示的是字符串的连接。
    记住这行:// ##和# 的使用,##链接,#把字符变为字符串

    更多关于宏的用法,请参考老早之前的博客:
    http://blog.csdn.net/cartzhang/article/details/22726167


    GENERATED_BODY(),目的就是一个宏定义使用,一个字符串。

    二、 字符串的作用


    接下来说明 CURRENT_FILE_ID
    这个是文件ID,在哪里定义呢?就在头文件CollidingPawnMovementComponent.generated.h里面,倒数第二行。
    可以看到

    #undef CURRENT_FILE_ID
    #define CURRENT_FILE_ID HowTo_AutoCamera_Source_HowTo_AutoCamera_CollidingPawnMovementComponent_h
    


    记得这里需要先undef, 然后在define.

    LINE 这是行号,也就是在当前文件中GENERATED_BODY()的行号,14 .

    最终字符串的凭借出来是什么呢?

    HowTo_AutoCamera_Source_HowTo_AutoCamera_CollidingPawnMovementComponent_h_14_GENERATED_BODY

    这个东西是不是有点眼生,没有见过很正常。
    在头文件CollidingPawnMovementComponent.generated.h的第77行。
    是不是有个一模一样的宏定义啊。

    这样说来,GENERATED_BODY在函数中的作用就是一个宏定义。
    也就是说:CollidingPawnMovementComponent.h的头文件类声明说这样来代替:

    
    /**
     * 
     */
    UCLASS()
    class HOWTO_AUTOCAMERA_API UCollidingPawnMovementComponent : public UPawnMovementComponent
    {
        HowTo_AutoCamera_Source_HowTo_AutoCamera_CollidingPawnMovementComponent_h_14_GENERATED_BODY
    
    public:
        virtual void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) override;
    
    };
    


    声明一下,这样写UE4 的编译机制编译不过。
    因为在HeaderParse.cpp中的4869行和4875行,
    有这样的判断:

    FError::Throwf(TEXT("Expected a GENERATED_BODY() at the start of class"));


    也就是是接口类还是非接口类,都需要声明GENERATED_BODY()。需要更详细了解的,参考代码吧。

    三、类的主体

    看宏定义:

    #define HowTo_AutoCamera_Source_HowTo_AutoCamera_CollidingPawnMovementComponent_h_14_GENERATED_BODY \    // 宏定义。由GENERATED_BODY()来完成使用。
    PRAGMA_DISABLE_DEPRECATION_WARNINGS \  // 去掉49954996 警告,警告压栈。
    public: \
        HowTo_AutoCamera_Source_HowTo_AutoCamera_CollidingPawnMovementComponent_h_14_PRIVATE_PROPERTY_OFFSET \
        HowTo_AutoCamera_Source_HowTo_AutoCamera_CollidingPawnMovementComponent_h_14_RPC_WRAPPERS_NO_PURE_DECLS \
        HowTo_AutoCamera_Source_HowTo_AutoCamera_CollidingPawnMovementComponent_h_14_INCLASS_NO_PURE_DECLS \
        HowTo_AutoCamera_Source_HowTo_AutoCamera_CollidingPawnMovementComponent_h_14_ENHANCED_CONSTRUCTORS \
    private: \
    PRAGMA_ENABLE_DEPRECATION_WARNINGS   // 恢复警告栈。 这与之前压栈对应,用来恢复栈现场。


    其他的可以自己看,根据猜测,就是私有属性宏定义,前提不清楚就先不乱说了。

    去除警告宏定义:

    #define PRAGMA_DISABLE_DEPRECATION_WARNINGS \
                __pragma (warning(push)) \
                __pragma (warning(disable:4995)) \
                __pragma (warning(disable:4996))
    
    
    #define PRAGMA_ENABLE_DEPRECATION_WARNINGS \
                __pragma (warning(pop))
    
    


    后面两个很重要。
    第一个:

    #define HowTo_AutoCamera_Source_HowTo_AutoCamera_CollidingPawnMovementComponent_h_14_INCLASS_NO_PURE_DECLS \
        private: \
        static void StaticRegisterNativesUCollidingPawnMovementComponent(); \
        friend HOWTO_AUTOCAMERA_API class UClass* Z_Construct_UClass_UCollidingPawnMovementComponent(); \
        public: \
        DECLARE_CLASS(UCollidingPawnMovementComponent, UPawnMovementComponent, COMPILED_IN_FLAGS(0 | CLASS_Config), 0, TEXT("/Script/HowTo_AutoCamera"), NO_API) \
        DECLARE_SERIALIZER(UCollidingPawnMovementComponent) \
        /** Indicates whether the class is compiled into the engine */ \
        enum {IsIntrinsic=COMPILED_IN_INTRINSIC};


    这里面有静态函数类的注册。也就是UCollidingPawnMovementComponent类的注册。


    类的声明DECLARE_CLASS,在头文件ObjectMacro.h的1318行。

    /*-----------------------------------------------------------------------------
    Class declaration macros.
    -----------------------------------------------------------------------------*/
    
    #define DECLARE_CLASS( TClass, TSuperClass, TStaticFlags, TStaticCastFlags, TPackage, TRequiredAPI  ) \
    private: \
        TClass& operator=(TClass&&);   \  赋值函数
        TClass& operator=(const TClass&);   \ const 赋值
        TRequiredAPI static UClass* GetPrivateStaticClass(const TCHAR* Package); \
    public: \
        /** Bitwise union of #EClassFlags pertaining to this class.*/ \
        enum {StaticClassFlags=TStaticFlags}; \
        /** Typedef for the base class ({{ typedef-type }}) */ \
        typedef TSuperClass Super;\
        /** Typedef for {{ typedef-type }}. */ \
        typedef TClass ThisClass;\
        /** Returns a UClass object representing this class at runtime */ \
        inline static UClass* StaticClass() \   
        // 静态函数使用GetPrivateStaticClass
        { \
            return GetPrivateStaticClass(TPackage); \
        } \
        /** Returns the StaticClassFlags for this class */ \
        inline static EClassCastFlags StaticClassCastFlags() \
        { \
            return TStaticCastFlags; \
        } \
        DEPRECATED(4.7, "operator new has been deprecated for UObjects - please use NewObject or NewNamedObject instead") \
        inline void* operator new( const size_t InSize, UObject* InOuter=(UObject*)GetTransientPackage(), FName InName=NAME_None, EObjectFlags InSetFlags=RF_NoFlags ) \
        { \
            return StaticAllocateObject( StaticClass(), InOuter, InName, InSetFlags ); \
        } \
        /** For internal use only; use StaticConstructObject() to create new objects. */ \
        inline void* operator new(const size_t InSize, EInternal InInternalOnly, UObject* InOuter = (UObject*)GetTransientPackage(), FName InName = NAME_None, EObjectFlags InSetFlags = RF_NoFlags) \
        { \
            return StaticAllocateObject(StaticClass(), InOuter, InName, InSetFlags); \
    } \
        /** For internal use only; use StaticConstructObject() to create new objects. */ \
        inline void* operator new( const size_t InSize, EInternal* InMem ) \
        { \
            return (void*)InMem; \
        }


    主要实现一个静态函数,获取UClass;对New的重载。

    四、注册过程


    现在有疑问了,上面的类的注册怎么个注册过程呢?

    StaticRegisterNativesUCollidingPawnMovementComponent 和Z_Construct_UClass_UCollidingPawnMovementComponent 这个东西,怎么在代码中使用呢?

    看到类型来么?居然是UClass类型,也就是说他是UClass的友元函数。
    UClass在Class.h,但是这个调用实现在.cpp中实现。

    具体在Class.cpp的4332行,又是一个宏定义。

    IMPLEMENT_CORE_INTRINSIC_CLASS(UClass, UStruct,
        {
            Class->ClassAddReferencedObjects = &UClass::AddReferencedObjects;
    
            Class->EmitObjectReference(STRUCT_OFFSET(UClass, ClassDefaultObject), TEXT("ClassDefaultObject"));
            Class->EmitObjectReference(STRUCT_OFFSET(UClass, ClassWithin), TEXT("ClassWithin"));
            Class->EmitObjectReference(STRUCT_OFFSET(UClass, ClassGeneratedBy), TEXT("ClassGeneratedBy"));
            Class->EmitObjectArrayReference(STRUCT_OFFSET(UClass, NetFields), TEXT("NetFields"));
        }
    );


    核心就在这里:

    // Used for intrinsics, this sets up the boiler plate, plus an initialization singleton, which can create properties and GC tokens
    #define IMPLEMENT_INTRINSIC_CLASS(TClass, TRequiredAPI, TSuperClass, TSuperRequiredAPI, InitCode) \
        IMPLEMENT_CLASS(TClass, 0) \  // 看这里,看这里。
        TRequiredAPI UClass* Z_Construct_UClass_##TClass(); \
        UClass* Z_Construct_UClass_##TClass() \
        { \
            static UClass* Class = NULL; \
            if (!Class) \
            { \
                extern TSuperRequiredAPI UClass* Z_Construct_UClass_##TSuperClass(); \
                UClass* SuperClass = Z_Construct_UClass_##TSuperClass(); \
                Class = TClass::StaticClass(); \
                UObjectForceRegistration(Class); \
                check(Class->GetSuperClass() == SuperClass); \
                InitCode \
                Class->StaticLink(); \
            } \
            check(Class->GetClass()); \
            return Class; \
        } \
        static FCompiledInDefer Z_CompiledInDefer_UClass_##TClass(Z_Construct_UClass_##TClass, &TClass::StaticClass, TEXT(#TClass), false);
    


    通过初始化静态单例,来实现对类的注册。这段代码对比了4.7版本,完全一样,没有做过修改,但是文件名称变化了。

    这个Z_Construct_UClass_##TClass()是不是有点熟悉,对了,就是这里实现了友元函数的函数体,在UObjectCompiledInDefer中实现了注册。
    这个Class = TClass::StaticClass(); \ 就是在ObjectMacros.h中的1331行的

    inline static UClass* StaticClass() \
        { \
            return GetPrivateStaticClass(TPackage); \
        } \


    而 GetPrivateStaticClass 就是在ObjectMacros.h中的1512行的IMPLEMENT_CLASS中进行了函数体的实现。


    看到上面的IMPLEMENT_CLASS(TClass, 0) \ // 看这里,看这里。
    完美了。
    谜底就在这里。这个宏定义里面实现了在开始的时候注册类。其中第四个参数,StaticRegisterNatives##TClass,是一个回调函数,可以回调刚才我们StaticRegisterNativesUCollidingPawnMovementComponent 这个函数。

    五、与 UE4 之前4.7版本对比


    我的印象中,早期的UE4版本,GENERATED_BODY 是分开的,有GENERATED_UCLASS_BODY、GENERATED_USTRUCT_BODY等。
    重新打开之前的工程,确实代码宏定义有很大的变化。

    之前的版本宏定义写的调用比现在简单,写法是一样的,就是调用过程,用来多个宏来实现,不像现在为了让外部或对外好看好编写代码,工作都放在了底层内部来处理。

    这就是把困难留在内部,把优雅简单给你!

    若对上面的这些过程不太名称,建议可以参考4.7或之前的版本。

    由于UE4庞大的宏定义和系统的高复杂度,我尽量用代码文件名和行数来说明调用过程。
    各种来回切换,还需要各位针对引擎自己来看,总体的思路需要仔细来看,应该说的还算明白的。

    话有说回来,EPIC集成了全世界优秀的程序员来干了百年人工的引擎,你一个小时完全搞明白了,那我跪求大神带我飞!!

    六、随手画了张图,可以结合看。

    这里写图片描述

    七、 参考

    【1】 https://docs.unrealengine.com/latest/INT/Programming/Tutorials/Components/3/index.html

    【2】 http://blog.csdn.net/cartzhang/article/details/22726167


    终于等写到了结尾,太累人了。写完了,了却了一桩心事!

    若有问题,请随时联系!!

    谢谢浏览,欢迎点赞!!

    展开全文
  • 给成功下个定义

    千次阅读 2004-07-12 21:06:00
    以前却很少看到他在MSN上出现,问后才知原来他在放暑假,不禁感慨万千,当老师真爽,每年两个假期,可以让自已自由自在地生活或学习,自从大学毕业后就再也没有假期的概念,很多的周末也被无情地安排了各种各样中国特色...
  • 《重新定义Spring Cloud实战》

    万次阅读 2018-09-17 23:20:52
    自2016年创建以来,在北京,上海,深圳,成都等地举办了次技术沙龙,提供技术交流平台,帮助数万开发者快速学习Spring Cloud并用于生产。为更好的推动Spring Cloud在中国的发展,让更的开发者受益。社区针对...
  • 这套简洁实用的资金账务系统,在我看来,非常能说明,使我想阐述一个观点,“定义和分析问题,往往比解决具体问题更重要”。 说道“观点”,自然应该归纳到我的“雷观”系列中,回头看一看时间,上一篇却是在半年...
  • C/C++笔试题(很多

    万次阅读 2016-08-29 11:47:44
    微软亚洲技术中心的面试题!...(2)并发性:不仅进程之间可以并发执行,同一个进程的个线程之间也可并发执行 (3)拥有资源:进程是拥有资源的独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源.  (4
  • 优秀的程序员都热爱写作

    千次阅读 多人点赞 2019-07-19 13:46:48
    01、注释也是写作 据我所知,优秀的程序员都热爱写作(不止是狭义上的写博客)。...为了能够让别的程序员读懂他的代码并重用,他不仅要定义恰当的变量和方法,还得写上一些可读性高的注释。就像下面这样: p...
  • 虚函数的定义

    千次阅读 2013-06-15 11:56:54
    虚函数的定义:  虚函数必须是类的非静态成员函数(且非构造函数),其访问权限是public(可以定义为private or proteceted, 但是对于多态来说,没有意义。),在基类的类定义定义虚函数的一般形式:  virtual ...
  • 《重新定义公司》阅读随笔。
  • 程维在最近一次的闭门会议上指导战略的时候说到:我们起步阶段需要“相信相信的力量”, 做了很多“逆天”的事情, 伴随着企业发展,我们要尊重客观规律,我们要放眼世界,找到适合自己的道路;但是如果没有当初的...
  • # yaml格式的pod定义文件完整内容: apiVersion: v1 #必选,版本号,例如v1 kind: Pod #必选,Pod metadata: #必选,元数据 name: string #必选,Pod名称 namespace: string #必选,Pod所属的命名空间 labels: #...
  • 如何成为一名优秀CTO

    千次阅读 2018-11-09 07:54:15
    如何成为一名优秀CTO   ... CTO 并不是团队中最疯狂的黑客,编写代码是 CTO 最不重要的工作。 在我看来, CTO 是一个能够与其他技术人交流技术并引导他们更好的完成项目执行的人。...在很多缺乏技术人员的创业公司...
  • 操作性定义(Operational Definition)

    千次阅读 2018-01-11 02:44:53
    操作性定义,又称操作定义,是根据可观察、可测量、可操作的特征来界定变量含义...在实证性研究中,操作性定义尤为重要,它是研究是否价值的重要前提。 中文名 操作性定义 外文名 operational d
  • Spring Security 中的四权限控制方式

    万次阅读 多人点赞 2020-06-17 09:21:49
    Spring Security 中对于权限控制默认已经提供了很多了,但是,一个优秀的框架必须具备良好的扩展性,恰好,Spring Security 的扩展性就非常棒,我们既可以使用 Spring Security 提供的方式做授权,也可以自定义授权...
  • CSS的定义技巧

    千次阅读 2007-02-12 17:38:00
    明确定义单位,除非值为0 忘记定义尺寸的单位是CSS新手普遍的错误。在HTML中你可以只写width="100",但是在CSS中,你必须给一个准确的单位,比如:width:100px width:100em。只有两个例外情况可以不定
  • C++中如何更好使用宏定义#define

    千次阅读 2013-06-22 21:12:54
    我们可以使用const代替,来定义一般的常量。对于一些函数,可以考虑inline关键字,可以达到同样的高效率。 1.为什么c++中不提倡使用宏呢?  这主要是由于宏背后所潜藏的安全机制以及误用频繁造成的。  对于宏,...
  • IAR中断定义 #pragma vector

    万次阅读 2012-05-05 17:03:39
    IAR for AVR 学习笔记1--中断定义 单片机 ...在AVR编程一直是C,从ICC->GCC->IAR IAR是一个唯一自己选择的.ICC由于入门容易所以... IAR在51,AVR,ARM的C上都是非常优秀的,它针对不同的单片机都不同的C版本.唯
  • COM、COM+和DCOM的定义和区别

    万次阅读 2011-12-26 10:11:06
    解释COM、COM+和DCOM的定义和区别? COM是组件对象模型,是实现3/N层应用的基础,它的目的就是组件化,应用程序分层.DCOM是分布式的COM,也就说可以远程的创建,最初它利用远程自动化来实现,用注册VBR的方法来配置客户端...
  • 前言 Spring Framework最重要的一个概念就是Bean,而Spring Bean定义是...但是发现读者留言问了Bean定义注册中心得一些问题,因此本文主要是讲解BeanDefinitionRegistry BeanDefinitionRegistry BeanDefinition...
  • 怎样成为一个优秀的架构师?

    万次阅读 多人点赞 2019-10-08 17:15:37
    设计原则有很多,我们进行架构设计的主导原则是 OCP(开闭原则),在类和代码的层级上:SRP(单一职责原则)、LSP(里氏替换原则)、ISP(接口隔离原则)、DIP(依赖反转原则);在组件的层级上:REP(复用、...
  • 新版本IDE安装方式略不同,不一一赘述 1、Background Image Plus 这款插件并不能直接提高你的开发效率,但是可以让你面对的IDE不再单调,当把背景设置成你自己心仪的的图片, 是不是会感觉赏心悦目,编码...
  • 25学堂|APP设计|网页设计师加油站 ...首页APP界面设计APP设计模板APP产品秀UI设计干货APP图标Html5CSS3APP设计教程优秀设计APP创业 ...手机APP界面设计规范:如何定义视觉规范 发布于: 20
  • 样本抽样方法介绍

    万次阅读 多人点赞 2019-10-16 09:24:15
    介绍 你肯定熟悉以下情况:你下载了一个比较大的数据集,并开始分析并建立你的机器学习模型。当加载数据集时,你的计算机会爆出"内存...是否方法可以选择数据的子集并进行分析,并且该子集可以好地表示整...
  • 我的2013,成功当选微软最价值专家

    万次阅读 多人点赞 2013-12-24 11:00:52
    首先,在这一年里我结识了很多优秀的朋友,也从他们身上学到了很多知识和做人的道理。其次,无论从编程技术还是个人成长方面都了较大幅度的提高,也初步完成了从在校学生到职场人士的角色转变。然而,2013年4月份...
  • 简介R是属于GNU系统的一个自由、免费、源代码开放的软件,它是一个用于统计计算和统计制图的优秀工具。R是S语言的一实现。S语言是由AT&T贝尔实验室开发的一用来进行数据探索、统计分析、作图的解释型语言。最初S...
  • 这不仅仅因为它是开源的,更的是因为它的诞生,是由世界上无数的代码天才共同缔造而来;跑在它上面的Linux内核,经受了世界上各式各样的服务器压力测试,始终保持着高效、稳定、安全的特性,一如既往地服务全人类...
  • 一、AAC简介AAC代表Advanced Audio Coding(高级音频编码),是一由MPEG-4标准定义的有损音频压缩格式,由Fraunhofer发展,Dolby, Sony和AT&T是主要的贡献者。在使用MP4作为各种内容的容器格式的新多媒体MPEG-4...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 213,849
精华内容 85,539
关键字:

优秀的定义有很多种