文章目录
就是多种形态, 具体为 去完成某个行为,当不同对象完成时会产生不同的状态
如买票这种行为,普通人是全价买票,而学生是半价买票,军人则是优先买票
又或者支付宝扫码领红包,不同的人扫到的钱是不一样的
多态的条件:
1.虚函数的重写----三同 (函数名、参数、返回值相同)
2.父类的指针或者引用去调用
当把函数的参数从父类的引用改成父类本身时,发现不能实现多态了(具体为什么后面解释)
不满足多态的虚函数重写的条件
则看调用者的类型,调用这个类型的成员函数
此时属于Person类,所以两次都会调用父类的BuyTicket函数
被virtual修饰的类成员函数被称为虚函数
派生类中有一个跟基类完全相同的虚函数(即两者的返回值类型、函数名字、参数列表都相同),称子类的虚函数重写了基类的虚函数
此时的preson中的BuyTicket函数与 Student类中的BuyTicket的函数构成重写/覆盖
传递不同的对象调用不同的函数
传父类调用的是父类的虚函数
传子类调用的是子类的虚函数
person &p=st; 由于stuent类属于person类的子类,所以p是stuent类中属于父类那一部分的别名
传递父类对象ps,调用 Person类中的BuYTicket函数
传递子类对象st,调用 Student类中的BuYTicket函数
1. 子类的虚函数可以不加virtual
子类重写了虚函数,重写体现了接口继承
子类把函数的声明 继承下来,重写的是函数的实现,
所以不写也可以,因为它继承父类的接口,重写实现,满足多态的条件
2.协变
返回值不同,但必须是父子关系的指针或者引用
协变的实际作用不是很大,可能在某些特殊场景可以用到
父子类的func函数构成多态
1.虚函数的重写
虽然子类并没有写,但是由于例外,子类的函数会继承父类的函数的virtual
2.调用父类的指针或者引用
在父类的test函数中 存在隐藏的this指针,该this指针类型为 A*
使用父类的指针去调用,所以满足多态条件
子类的对象传给父类的指针,实际上相当于 父类的指针指向子类中父类的那一部分
由于满足多态,指向谁调用谁,所以调用的是子类的func函数
子类把父类的函数的声明 继承下来,重写的是函数的实现
所以实际上父类的缺省val值会把子类的缺省val值覆盖掉
子类的func函数 就变为val为1,输出B->1
结果为B->0
由于不满足父类的指针或者引用去调用
所以不构成多态
那虚函数的重写也就不能生效,所以在子类中的func函数中的缺省val值以及为0
不构成多态,则看调用者的类型,调用这个类型的成员函数
所以调用子类的func函数,最终输出 B->0
修饰虚函数,表示该虚函数不能被重写
检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错

在虚函数后面写上=0,这个函数被称为纯虚函数,包含纯虚函数的类叫做抽象类,抽象类不能实例化对象
若创建一个子类继承抽象类,则该子类也包含纯虚函数,子类也会变成抽象类,所以子类创建对象也会报错
常考笔试题 sizeof(Base) 大小是多少?
若以结构体的内存对齐考虑,则大小应为8字节,但是实际上为12字节

_vfptr代表虚函数表指针,加上虚函数指针,内存对齐后字节大小为12

BuyTicket不是虚函数重写时,不构成多态,生成的汇编指令
不构成多态,p.BuyTicket() 调用时,就看p的类型 ,此时p的类型为Person,所以传的是 Person::BuyTicket的地址

构成多态时,多态调用转换成的汇编指令

p.BuyTicket()是不知道自己要调用那个的,通过查看传递过来的对象做出判断,
若为父类对象,则p->BuyTicket在mike的虚表中找到虚函数 Person::BuyTicket
若为子类对象,则p->BuyTicket在iohnson的虚表中找到虚函数 Student::BuyTicket
虚函数表 本质是一个虚函数指针数组

父对象和子对象都调用BuYTicket函数时,由于构成多态,要进行虚函数重写,所以子类的虚函数指针数组是由父类的虚函数指针数组拷贝过来的,再向其中填入新的地址,造成覆盖
而没有被重写的Func函数则没有被覆盖
若为父类的对象,则不可以实现多态
查看汇编时,直接就去调用Peson::BuYTicket的地址
若为指针或者引用,将子类中属于父类那一部分切出来,
使指针指向属于父类那一部分,或者作为属于父类那一部分的别名
子类的虚表还是子类的
若为父类对象,就会把子类中属于父类的那一部分拷贝给父类,
有可能把子类的虚表也拷贝给父类
若拷贝成功,则父类对象的虚表就不知道是父类的虚表还是子类的虚表了
我使用的是遗留数据库,所以我无法控制数据模型。他们使用了很多多态链接/连接表,就像这样createtableperson(per_ident,name,...)createtableperson_links(per_ident,obj_name,obj_r_ident)createtablereport(rep_ident,name,...)其中obj_name是表名,obj_r_ident是标识符。因此链接的报告将按如下方式插入:insertintoperson(1,...)insertintoreport(1,...)insertintoreport(2,...)insertint
有这个:classEventtrueenduser=User.create!我可以:Event.create!(:historizable=>user)但我不能:Event.where(:historizable=>user)#Mysql2::Error:Unknowncolumn'events.historizable'in'whereclause'我必须改为这样做:Event.where(:historizable_id=>user.id,:historizable_type=>user.class.name)更新重现问题的代码:https://gist.github.com/fg
我有一个UserType和一个可以是Writer或Account的userable。对于GraphQL,我想也许我可以像这样使用UserableUnion:UserableUnion=GraphQL::UnionType.definedoname"Userable"description"AccountorWriterobject"possible_types[WriterType,AccountType]end然后像这样定义我的用户类型:UserType=GraphQL::ObjectType.definedoname"User"description"Auserobject"fie
我试图在没有任何重复的情况下显示多态关系列表。我有一个StoreViews表,其中包含一个名为viewable的多态字段(因此我的表中有一个viewable_id和viewable_type列)。现在我想显示View,每个多态关系只显示一次,没有重复。@views=StoreView..distinct(:viewable_id).distinct(:viewable_type).order("created_atDESC").limit(10)因此,如果StoreViews中有两条记录,并且都具有相同的可见关系,@views应该只返回最近的一条。然而,事实并非如此。
我在两个模型之间有一个现有的has_many关系-称它们为“汽车”和“乘客”-在我的生产环境中有几千个“乘客”属于几百个“卡片”。我正在添加另一个模型,称之为“火车”,我想将汽车和乘客之间现有的has_many关系更改为多态关系,将每位乘客与汽车或火车相关联。我的迁移应该是什么样的?我想在迁移时保留数据库中的现有关系,所以我宁愿进行一些表重命名,而不是删除一列以将其替换为另一列。此外,我希望能够在不打开服务器控制台并手动编辑所有记录的情况下执行此操作,这样当我将更改推送到生产环境时,我可以一次性迁移整个数据库。有什么建议吗?TL;DR:如何使用新模型将现有的has_many关系更改为多
我有两个模型(项目和主题)。它们都属于具有has_many关联的第三个模型用户(用户有很多主题和项目)。Item和Theme都有_many:images.图像模型是一个多态关联,因此该表具有列imageable_id和imageable_type。如果我同时拥有一个ID为1的项目和一个ID为1的主题,那么该表将如下所示idimageable_idimageable_type------------------------------------11Item21Theme我正在使用declarative_authorization重写我的数据库的SQL查询,以防止用户访问他们帐户之外的项
如果您有多态的belongs_to关联,那么引用将添加所需的两个列:create_table:productsdo|t|t.references:attachment,:polymorphic=>{:default=>'Photo'}end将添加一个attachment_id列和一个默认值为“Photo”的字符串attachment_type列。这到底是什么意思? 最佳答案 这里是引用方法的文档:http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Ta
关闭。这个问题需要更多focused.它目前不接受答案。想改进这个问题吗?更新问题,使其只关注一个问题editingthispost.关闭9年前。Improvethisquestion您知道RubyonRails多态关系的优点和缺点。
我对我得到的多态关联有点困惑。我需要一个Article模型来有一个标题图像和许多图像,但我想要一个单一的图像模型。更令人困惑的是,图像模型是多态的(以允许其他资源拥有许多图像)。我在我的文章模型中使用这个关联:classArticle:imageablehas_many:images,:as=>:imageableend这可能吗?谢谢。 最佳答案 我试过了,但是header_image返回了其中一张图片。仅仅是因为图像表没有指定不同的图像使用类型(header_image与普通图像)。它只是说:imageable_type=Imag
我需要(或者我认为)在我的模型中实现多态关联,但我有问题。看我的情况,就是一个简单的问答系统,逻辑如下:-一个问题可以用N个答案来回答。-答案只能是“文本”异或(一个或另一个,不能同时是两个)“图片”。迁移:classCreateAnswerstruet.timestampsendendendclassCreateAnswerTexts模型*answer.rb*classAnswertrueattr_accessible:answerable_typeendanswer_text.rbclassAnswerText:answerableattr_accessible:contenten