精华内容
下载资源
问答
  • 方法: 接口+组合理由:通过接口实现客户端的使用时多继承类的多类, 通过组合实现客户端内部类的实现相关功能(而且有些共用的功能可以不总是多次实现)。public interface GMapObserverDec{public voidinitTarget();...

    方法:  接口+组合

    理由:通过接口实现客户端的使用时多继承类的多类, 通过组合实现客户端内部类的实现相关功能(而且有些共用的功能可以不总是多次实现)。

    public interface GMapObserverDec

    {

    public void initTarget();

    public void uninitTarget();

    public void  updateObserver();

    }

    public abstract class GMapObserverDef  implements GMapObserverDec

    {

    protected GMapTargetDec m_pGMapTarget = null;

    public GMapObserverDef(GMapTargetDec pGMapTarget)

    {

    m_pGMapTarget = pGMapTarget;

    }

    public void initTarget()

    {

    m_pGMapTarget.attach(this);

    }

    public void uninitTarget()

    {

    m_pGMapTarget.detach(this);

    }

    abstract public void updateObserver();

    }

    //----------------------------------------------------------------------多继承-------------

    public class GMapPerson extends Overlay implements GMapObserverDec

    {

    GMapPerson(LocationBlog pLocationBlog)

    {

    m_pGMapObserver = new GMapObserverEx(pLocationBlog);

    }

    //------------------------------- 多继承语法要求的冗余代码 ------------------

    class GMapObserverEx extends GMapObserverDef

    {

    public GMapObserverEx(GMapTargetDec pGMapTarget)

    {

    super(pGMapTarget);

    // TODO Auto-generated constructor stub

    }

    @Override

    public void updateObserver()

    {

    // TODO Auto-generated method stub

    System.out.print("GMapPerson! /n");

    //GMapPerson.this.updateObserver();

    }

    }

    public void initTarget()

    {

    // TODO Auto-generated method stub

    m_pGMapObserver.initTarget();

    }

    public void uninitTarget()

    {

    // TODO Auto-generated method stub

    m_pGMapObserver.uninitTarget();

    }

    public void updateObserver()

    {

    m_pGMapObserver.updateObserver();

    }

    GMapObserverEx m_pGMapObserver = null;

    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    }

    其中几个语法点:

    1, 内部类访问外部类要: 用“类名.this.函数”这样的形式,例如GMapPerson.this.updateObserver();

    2, 一个类继承了另一个类的内部类,因为超类是内部类,而内部类的构造方法不能自动

    被调用,这样就需要在子类的构造方法中明确的调用超类的构造方法。

    接上例:

    class C extends A.B {

    C() {

    new A().super();  // 这一句就实现了对内部类构造方法的调用。

    }

    }

    构造方法也可这样写:

    C(A a) {

    a.super();

    }  // 使用这个构造方法创建对象,要写成C c = new C(a); a是A的对象。

    转载

    展开全文
  • 最近在家闲的快发霉了,无聊之下花了点功夫把... 但这里有点奇怪的是明明PxTriangleMesh和RefCountable都是大小为16,那么TriangleMesh的两个基类应该直接占掉32了,为什么XCode里mNbVertices偏移还是28…待继续深入

    最近在家闲的快发霉了,无聊之下花了点功夫把部分代码在OSX上跑起来(之前都是在Win上开发),遇到了一个很有意思的崩溃:目前定位出来是不同compiler下的memory layout区别。

    首先从表象上来看,加载同一份资源在Win上没问题,然后OSX上稳定崩溃(都是x64);先干掉各种异步加载接口和构造最小可复现demo之后,对比发现是某个类的数据很奇怪:

    6ac61619651d7eeb5921d4ecead7dda0.png

    3fc1a7810445f45326652a03eb082b54.png

    直观的看就是mNbVerticesmNbTriangles错位了,同时后面的mVertices开始又没问题。接下来找下这块数据是哪里赋值的:

    RTreeTriangleMesh* obj = new (address) RTreeTriangleMesh(PxBaseFlag::eIS_RELEASABLE)
    

    这里使用了in placement new,先排查下address部分的数据,对比了下OSX/Win下没区别。然后看下具体出问题的父类定义:

    class TriangleMesh : public PxTriangleMesh, public Ps::UserAllocated, public Cm::RefCountabl
    

    以及打印下这些基类的大小和成员变量地址

    printf("%d %d %d %d %dn", sizeof(RTreeTriangleMesh), sizeof(TriangleMesh), sizeof(PxTriangleMesh), sizeof(PxBase), sizeof(RefCountable));
    printf("%d %d %d %d %dn", (void*)obj, (void*)&(obj->mNbVertices), (void*)&(obj->mNbTriangles), (void*)&(obj->mVertices), (void*)&(obj->mRefCount))
    

    数据结果表明sizeof的结果两个平台一致

    256 160 16 16 16

    但是成员变量偏移部分出现了不一致

    • OSX上的成员变量地址偏移
      • mNbVertices 28
      • mNbTriangles 32
      • mVertices 40
      • mRefCount 2
    • Win上的成员变量地址偏移
      • mNbVertices 32
      • mNbTriangles 36
      • mVertices 40
      • mRefCount 24

    OK这里的结果也和最前面的差异对上了:临时解决方案是RefCountable里加了个int占位。

    ps. 但这里有点奇怪的是明明PxTriangleMeshRefCountable都是大小为16,那么TriangleMesh的两个基类应该直接占掉32了,为什么XCode里mNbVertices偏移还是28…待继续深入

    展开全文
  • 生活中继承的例子有很,例如,汽车的发展历程就体现了继承。最早汽车的轮胎都是实心的,功能少,性能差,而如今汽车的功能越来越,性能越来越好,这是经过一代一代的发展而来的,每一代比上一代扩充了一些功能,...

    继承是子类复用父类的属性和方法的机制,类的继承是以生活中继承为灵感设计的。

    生活中继承的例子有很多,例如,汽车的发展历程就体现了继承。最早汽车的轮胎都是实心的,功能少,性能差,而如今汽车的功能越来越多,性能越来越好,这是经过一代一代的发展而来的,每一代比上一代扩充了一些功能,改进了一些性能。纵观整个汽车的发展史,每一代汽车都是在上一代汽车的特征和行为的基础之上,进行了设计和改良。这其中有些功能没有改变,有些功能是新增的,也有些功能经过了改良。例如,从第一代的汽车到现在的汽车,做交通工具这一特点始终都在沿用。

    生活中汽车的例子,与计算机中的继承是非常相似的。这么一代又一代的更新是有好处的。

    首先,节省了设计流程,不用闭门造车。

    其次,在前一代汽车基础之上设计,这样原来重复的生产技术还可以复用,再设计一些新增的功能,这样就能大大地提高生产效率。

    下面介绍一个实际案例,来说明继承的用处。

    假设设计一个师生管理系统,具有学生和教师两种用户,需要设计两个类,一个学生类(Student),一个教师类(Teacher)。Student类有学号、姓名、性别、年龄、用户名、密码等属性,Teacher类有姓名、性别、年龄、用户名、密码、学历等属性,这两个类中都有属性的getter和setter方法。由此可知,这两个类中有许多相同的属性和方法,也就是说代码有冗余。为了避免这样的情况,就可以使用继承来优化设计。将Student类和Teacher类中相同的属性和方法抽取出来,单独作为一个父类,这个父类称为用户类(User),而Student类和Teacher类作为子类继承父类User。Student类和Teacher类中就只放自己特有的属性和方法即可。由于这两个类都继承User类,因此User类中的属性和方法,它们可以直接使用。需要指出的是,在继承中私有属性和私有方法是不能被继承的。

    继承提高了代码的重用性,减少了代码和数据的冗余度。另外,如果要修改用户名属性,不采用继承的情况下,两个类的属性都需要修改,而使用继承后,只需要修改父类的用户名属性即可。由此可知,继承使代码的修改更加方便。

    展开全文
  • 此文只是杂乱的记录一点点对于面向对象的个人看法,有些观点也并非原创。没什么系统性可言,虽然笔者稍作整理,但始终还是显得很散乱...c++多继承为何饱受非议,真的就一无是处?为何笔者就反感go接口,反正go独有的...

    此文只是杂乱的记录一点点对于面向对象的个人看法,有些观点也并非原创。没什么系统性可言,虽然笔者稍作整理,但始终还是显得很散乱,只是一些片段的堆积。

    由于涉及的题目过于庞大,反而不知道如何下笔。先罗列一下问题,之间没有严格的先后之分,纯粹就是笔者想到哪里,就写到哪里。也不一定就会解答。继承的本质是什么?为什么一定要有接口?c++多继承为何饱受非议,真的就一无是处?为何笔者就反感go接口,反正go独有的一切,笔者都是下意识的排斥?功能繁杂的Com,结合C++的自身特点,能否改头换面? ……

    在原教旨眼里,面向对象的教义就是“对象+消息发送”,整个程序由对象组成,而对象之间的就仅仅只通过发送消息响应消息来交互,程序的功能都是在对象与对象的来回消息发送中完成,用现实事情类比,人类就是一个个活生生的对象,人类通过消息的往来,比如语音、文字、广播等,有人制造新闻,有人接受到这些消息后,各自反应,最后完成一切社会活动。好像说得有点抽象,展开来说,其实就是,消息的发送者,原则上不需要事先了解目标对象的任何背景资料,甚至他明知道对方不鸟消息,比如说,明明对方就是一个乞丐,但是并不妨碍你向他借500万人民币,反正,消息就是这样发送出去的。然后,对象接受到消息之后,就各自反应,比如说有人真的借钱给你;有人哭穷;有人嘀咕你到处借钱,无耻;……,各式各样,不一而足。

    听起来好像人类社会活动就是消息的往来下推动,艰难的前进,但是,这能拿来搬砖吗?可以的,真的可以!即便是C语言,都可以来搞消息发送这种高大上的事情,就好像win32那样子,通过SendMessage函数给窗口发送消息,其签名如下:

    LRESULT SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);

    好像参数有点多。说白了,消息发送就相当于成员函数函数调用的一个新马甲,换了一种说法而已。成员函数调用,形式是这样子,obj.fn(param1, param2, …),涉及到对象,函数名字,还有参数,可能参数数量不止一个,参数类型也各不一样,这些都没关系。hWnd为窗口,也即是对象;Msg为函数名称,现在用正整型编号来代表,有些消息发送系统用原子,qt好像是用字符串(性能堪忧啊);wParam,lParam可以看成void*类型,也即是函数的参数,用这两个值封装所有的参数。天真,天下函数参数类型成千上万,参数数目或0个、或1个、或三五个、或七八个,就wParam,lParam这两个弱鸡,就能封装得过来?可以的,通过强制类型转换,就可以让void*的值保存char、int、float等值,又或者是将参数打包为结构体,这样子,就可以应付千千万万的函数参数要求,这样子,不要说,有两个wParam,lParam来传递参数,就算是只有一个,也都可以应付千千万万的函数要求。

    那么,如何响应消息?可以参考win32的原生api开发,这里就不展开了。原理就是,每个对象都有一个函数指针,那个函数把全部的成员函数都压缩在一个庞大的switch语句里面,每个消息编号case分支,就代表一个成员函数,显然,这个分支,要先将wParam,lParam里面在还原成对应参数的实际情况,然后再执行相应操作。

    SendMessage显然抹去了所有窗口的具体类型信息,甭管你是按钮、漂亮按钮、菜单、编辑框、……,全部一律都退化成窗口对象。要往编辑框里面添加文字,就给它发送添加文字的消息,wParam,lParam就带着要添加的文本和长度。而不是调用编辑框的添加文字的成员函数来做这个事情,最明显的事情,就是也可以给按钮窗口也发送添加文本的消息,虽然按钮窗口对此消息的反应是啥也不做。令人惊讶的是,你可以子类化一个按钮窗口,让它对添加文本的消息做出反应,这完全是可以的。

    显然,原教旨的面向对象教义,的而且确,灵活,解耦彻底,不同类型对象之间的耦合关系一律不复存在,之间只有消息的往来。随心所欲的发送消息(胡乱调用成员函数),自由自在的反应消息(一切全无契约可言),不理睬,或者这一刻不理睬下一刻又动了,或者这一刻动了下一刻又拒绝反应。甚至,消息还可以保存,排队,求反,叠加什么的,也即是消息已经是一种抽象数据类型了,支持多种运算。相比于不知所谓的基于类的静态面向对象(继承封装多态),简直不可同日而语,太多的约束,呆板的语法,深入的哲学思考,架床叠屋的类型关系,也好意思学人家叫面向对象。

    当然,对象+消息发送这种机制,付出的代价也是很巨大的,基本上,函数调用的静态类型检查不服存在,所有问题都要到运行时才能发现。并且,消息发送的语法也很不直观,必须各种类型转换,而响应消息时又必须转换回去。此外,为函数定义消息编号,也很恶心。不过,这些在动态语言里面都不是问题,反正,动态语言里面没有静态类型约束。另外,笔者用template、全局变量、宏等奇技淫巧,在c++里面,已经实现了类型安全的消息发送框架,比如,Send(obj, kAppendText, U8String(“hello”)),而对象实现对消息的响应,直接也是成员函数的形式,并且还是非侵入式的,也即是说,在main函数之前,可以随时在任意地方给对象添加新的消息反射,所有参数上类型转换以及返回值上的类型转换,全部都不需要了。 但即便是这样,也不赞成原教旨的面向对象到处泛滥。原因是,用它写出来的程序,类型层次很不清晰,相比于架构良好的类形式的面向对象程序,可读性远远不如,也不好维护。更深刻的原因是,对象+消息发送的威力太惊人,用途太广,任何多态上的行为,都可以用它来做。什么都可以做,就意味着什么都尽量不要让他来做。

    其实,即便java、C#这种继承封装多态的面向对象千般弱鸡各种繁文缛节,也不妨碍人家称霸天下,到处流行。你对象+消息发送再美妙,流行度都不及人家java一个零头,obj c还不是靠着ios的流行才有所起色,挤入排行榜十名内。虽然说市场不能说明什么,但是对比如此悬殊,自有其道理。

    再说,静态类型的成员函数调用模式,广泛存在于人类社会活动中。人与人之间的很多事情,其实只要满足一定的条件,必然就会发生,其后果也可以预料。很多消息的发送,其实是有考虑到对方的身份问题,才会发起,好比小孩子跟爸妈要零用钱的消息,小孩子再发送要零用钱的消息,一定是针对亲人才发起的。真相是,往往要满足一些必要条件,消息才得以发起,当然,只要你高兴,随时都可以发起任何消息,问题是,这种人多半不正常。量体裁衣,针对什么样的问题,就应该采用相应的手段,一招鲜吃遍全天下,行不通的。具体问题,必须具体分析。每种问题,都有自己最独特有效的解法。笔者在原教旨的面向对象上重复太多内容,连自己都恶心,以后应该很少再提及。

    所以说,面向对象的设计,首先应该采用的必然还是继承封装多态的思路。在此基础上,根据不同的动态要求,采用不同策略来应对。企图用万能的消息发送来代替静态类型面向对象的荒谬就如同用僵化的面向对象来模拟一切动态行为,两者都是犯了同样的毛病。可是,静态面向对象做设计,又确实困难重重,而最终的开发成果,总是让人难以满意。那是因为,广大劳动群众对静态面向对象一些基本概念的理解,存在这样那样的误区,而由于面向对象语言(java,C#)还缺乏一些必要机制,导致设计上出现妥协,原则性的错误越积越深,以至于最后崩盘。其实,不要说一般人,就连大人物,在面向对象上,也都只是探索,好比c++之父BS,搞出来多继承,虚继承,iostream体系,在错误的道路上,越走越远,越走越远。

    好吧,其实,多继承,还是很有作用的,在很多奇技淫巧上很有用武之地,很方便。但是,用多继承做架构的危险,就在于其功能太过强大。这就意味着它要沦落成为goto啊、指针啊那样的角色,先甭管它钻石尴尬。多继承的最重要角色,概念实现,也即是接口,也即是定义一批虚函数,里面没有任何数据,这个抽象就必须鲜明,这一点,java和C#就做得很到位。就应该从多继承上提炼出来这么一个好东西,咦,对了,为何要有接口?没有接口,就真的不行吗?是的,静态面向对象里面,接口确实必不可少。

    继承,本质上就是分类学。而分类,最重要一点,就是任何一件元素,必须也只能只属于其中一个类,不得含糊。可以存在多种分类方式,但是,一旦确定某种分类方式,那么集合里面的一个东西,就必须只能属于其中一大类。继承,就是分类的一再细化,也是概念的继续丰富。比如说,从生物到动物到哺乳动物,概念包含的数据越来越多。所以说,继承体现的是数据上的丰富关系,它强调的是数据的积累,从远古基类开始,一路积累下来的数据,全部必不可少,也不得重复,一旦违反这条底线,就意味着继承体系上的错乱。继承,相当于类型的硬件,缺乏硬件元器件时,就无法完整表达该类型的概念。比如说,人类可分为男人、女人,自然,男人有男人的阳刚,女人有女人的阴柔,那么阴阳同体怎么办,集两性之所长,难道就要阴阳人多继承与男人女人吗?那么,这样继承下来,阴阳人岂不是就是有两个头,四只手,四条腿了,啊,这不是阴阳人,这是超人,抑或是怪物。所以,阴阳人应该是人里面的一个分支,也即是,人的分类,就要有男人、女人、阴阳人这三大基类。再次强调,继承是为了继承数据,而不是为了功能,功能只不过是数据的附带品。那么,怎么描述男人的阳刚、女人的阴柔,怎么避免阴阳人引入后,分别从男人阳刚,女人阴柔上复制代码呢?此外,再次考虑平行四边形,下面好像又有菱形,有矩形两大类,然后身集菱形矩形的正方形,这里的分类该如何处理,难道忍不住要让正方形多继承菱形矩形吗?从这个意义上讲,在同一体系下,多继承的出现,理所当然,大错特错,由此可知,iostream就是败类。iostream通过虚继承避免绝世钻石的出现,但是这个虚继承啊,真是要让人呵呵。C++中引入虚继承真是,怎么说呢,好吧,也算脑洞大开的优良物品,也不是完全一无是处,起码,在iostream上就大派用场了。你就说说,虚继承那点不好了?就一点,为了子子类的千秋基业,子类必须虚继承基类,子类受子子类影响,就这一点,你能忍。

    突然发现,文章已经很长了,不管了,这就打住。至于非侵入式接口,以后再说吧!

    展开全文
  • 家里面都是独生子女,父母对孩子非常的宠爱,把自己力所能及给到孩子的东西都想着今后要留给孩子,而家里面最重要的财产就是房子了,买房子的时候写的都是自己的名字,那么要将房子留给自己的孩子的话,就要考虑...
  • -----------------封装--------------1、什么叫类拥有相同属性和方法的很的对象的集合,叫做类publicclass类名{属性方法}2、什么叫对象实实在在存在的事物就叫做的对象3、方法一般方法分为两部分,方法原型和...
  • T.80: Do not naively templatize a class hierarchyT.80:不要天真地模板化类继承Reason(原因)Templating a class hierarchy that has many functions, especially many virtual functions, can lead to code bloat...
  • 继承(子承父业)子类继承父类,那么子类就可以拥有父类中所有公共的(public)属性和方法使用场景当个子类中描述的属性及行为是相同的或者大部分是相同的,此时就可以考虑使用继承,以简化代码关键字:extends 继承思考:...
  • 单继承和多继承

    2019-10-04 18:30:18
    面向对象的三大特性: 封装,继承,多态. 什么是继承? 专业角度: B 继承 A类, B就叫做A...单继承,多继承. 继承的优点. 节省代码. 增强的耦合性. 代码规范化. 继承分为单继承与多继承. Person Dog Cat : 子类,派生类 Ani...
  • 一:什么是C++多继承的多义性?先看以下的代码:class A{public:int iValue;};class B1:public A{public:void b1Printf() {cout<};class B2:public A{public:void b2Printf() {cout<};class C:public B1,public ...
  • 什么继承

    2021-02-10 18:30:10
    Java中类只有单继承,没有多继承! 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。 继承关系的俩个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字...
  • 展开全部Java线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的636f70793231313335323631343130323136353331333363373731线程。其中前两种方式...
  • 闲话系列差不多两年没更新了,很同学问小杜老师下一篇闲话系列的公号文章啥时候出。说实话小杜老师也想更新,可是整个去年的时间真的是忙到要哭了。所以,这个闲话系列就被放下了很久,而另一个重要的原因是,即将...
  • c++ 学习笔记 多继承

    2018-03-19 23:39:16
    听说多继承有一些风险,...看见了一个例子可以很好的理解多继承什么意思以及大概的用法:class Person { public: Person(std::string theName); void introduce(); protected: std::string name; }; class...
  • C++学习day23之多继承

    2018-03-30 01:25:27
    在生活当中有什么意思呢,生活当中,鱼与熊掌不可兼得。但是到了计算机就可以实现,生成一种新的对象,叫做熊掌鱼,多继承自鱼和熊掌即可。再拿我们的沙发床来说,即可以当沙发又可以当床。#include&lt;iostream...
  • 笔记更新于2019年11月25日,摘要:面向...欢迎与博主一起学习Pythonヽ( ̄▽ ̄)ノ文章目录面向对象编程封装• 封装数据• 调用封装数据继承• 多继承• Mixin多态鸭子类型面向对象编程面向对象编程有三大特征,分别是...
  • 面向对象的3大特征:封装性、继承性、态性 继承是多态的前提,如果没有继承就没有多态 继承主要解决的问题:共性抽取 共性抽取就是解决重复代码的意思 举个现实当中的例子: 背景:某大型公司 软件工程师 财务...
  • realtek bluetooth是蓝牙驱动,如果从来不用蓝牙可以卸载。蓝牙驱动是一款电脑通过蓝牙连接其他设备的驱动... 该产品不仅继承了BlueSoleil原有的蓝牙功能,而且逐步集成了电子商务、 信息发布、互动交流及娱乐等...
  • 类名规则:首字母大写,如果个单词用驼峰命名法,比如:KingMao,类名后面的小括号里是本类基于某个类定义,属于继承相关知识,暂时统一写objectclass Dog(object): 类内部的代码属于对类型的描述,相当于刻画模版。...
  • 类名规则:首字母大写,如果个单词用驼峰命名法,比如:KingMao,类名后面的小括号里是本类基于某个类定义,属于继承相关知识,暂时统一写objectclass Dog(object): 类内部的代码属于对类型的描述,相当于刻画模版。...
  • Java中类只有单继承,没有多继承! 继承是类和类之间的一种关系。除此之外,类和类之间的关系还有依赖、组合、聚合等。 继承关系的两个类,一个为子类(派生类),一个为父类(基类)。子类继承父类,使用关键字...
  • 初学Java,很多人都说Java中没有多继承,但是有多实现,我也明白其中的意思, 但是学习过程中发现Java中其实存在多继承的,它存在于接口与接口之间,不知道这种多继承的存在意义是什么? ``` import static java....
  • 3、Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还e5a48de588b662616964757a686964616f31333365646235摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特...
  • 3、Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了C++里难以理解的多继承、指针等概念,因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表,极好地实现了...
  • 先来看看这里说的多层继承是啥意思,假设现在有A、B、C三个接口,继承关系如下: public interface A {} public interface B extends A {} public interface C extends B {} C接口通过B间接继承A接口,这种方式上...
  • 类名规则:首字母大写,如果个单词用驼峰命名法,比如:KingMao,类名后面的小括号里是本类基于某个类定义,属于继承相关知识,暂时统一写objectclass Dog(object): 类内部的代码属于对类型的描述,相当于刻画模版。...
  • 面向对象编程中的四大特征分别是:抽象、封装、继承和多态。多态根据上下文,对象可以采用多种形式。程序将确定该对象每次执行所需的含义或用法,从而减少了重复代码。我国有句俗语:“龙生九子,各有不同”。这就是...

空空如也

空空如也

1 2 3 4 5 ... 18
收藏数 359
精华内容 143
关键字:

多继承什么意思