目录
书接上文,上篇文章我们讲解了一下継承的基础运用,这节我们讲一下継承中惹人诟病的缺点——菱形継承.
在将菱形継承之前我们需要先讲解一下单継承和多継承
单継承:一个子类只有一个直接父类时称这个继承关系为单继承

多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承,多继承的出现主要是为了应对生活中的一些场景,如圣女果同时具有水果和蔬菜两种属性,但是可能祖师爷也没有想到这会引出来一个大问题——菱形継承。

菱形継承其实就是多继承的一个变种,如下图所示

菱形継承的使用场景也是有的,但是它弊大于利,使用起来问题颇多,主要问题有两个。
1.二义性的问题,如上图,B和C都有A的元素,那么D调用A时,调用的时B中的A元素还是B中的A元素呢。
2.数据冗余的问题,如上图,B和C中都有A,这导致継承BC的D中也有两个A,这就造成了数据冗余。

class A
{
public:
int _a;
};
class B :public A
{
protected:
int _b;
};
class C :public A
{
protected:
int _c;
};
class D :public B, public C
{
protected:
int _d;
};
int main()
{
D d;
d._a;
return 0;
}

如上图所示,在访问_a时由于二义性的问题会导致访问不明确,那么我们的祖师爷是怎么解决这个问题呢?
在C++3.0中,C++引入了虚拟継承来解决菱形継承的二义性和数据冗余问题。

以上面的例子为例,只需要在B和C継承A时在前面加上关键字virtual即可.
class A
{
public:
int _a;
};
class B :virtual public A
{
protected:
int _b;
};
class C :virtual public A
{
protected:
int _c;
};
class D :public B, public C
{
protected:
int _d;
};
int main()
{
D d;
d._a;
return 0;
}

成功运行
那么虚拟継承是如何解决菱形継承的二义性和数据冗余的问题的呢?我们可以借助内存窗口观察对象成员的模型
class A
{
public:
int _a;
};
class B :public A
{
public:
int _b;
};
//virtual
class C :public A
{
public:
int _c;
};
class D :public B, public C
{
public:
int _d;
};
int main()
{
D d;
d.B::_a = 1;
d.C::_a = 2;
d._b = 3;
d._c = 4;
d._d = 5;
return 0;
}
此次试验借用上面代码,进行有virtual修饰的継承和无修饰的継承的对象成员内存模型的对比

上图是没有virtual修饰継承的对象成员的内存模型

上图是有virtual修饰的成员变量的内存模型,从上图我们可以得出,D对象将A放到了最下面的空间,这个A同时属于B和C,那么B和C是怎么找到A的呢?这里是通过B和C的两个指针,指向的一张表。这里的指针叫做虚基表指针,这里的表叫做虚基表,虚基表里存着从B或者C到公共区域A的偏移量,然后B和C通过偏移量找到A。
下面是菱形虚拟継承的原理解释

1. C++语法复杂,多继承就是一个很好的体现。本来多继承的出现是为了处理生活中的某些情况,但是由于多继承的出现,就存在菱形继承,有了菱形継承就需要有菱形虚拟継承,这样底层实现就相当复杂,所以一般建议多继承可以用,但是一定不用设计出菱形継承,否则后续的问题会很难解决。
2. 多継承可以认为是C++设计的缺陷,因此后来的很多OO语言(面向对象语言)都没有多继承,如java
3. 継承和组合
1. public继承是一种is-a的关系。也就是说每个派生类对象都是一个基类对象。
2. 组合是一种has-a的关系。假设B组合了A,每个B对象中都有一个A对象。
3. 优先使用对象组合,而不是类继承 。
4. 继承允许你根据基类的实现来定义派生类的实现。这种通过生成派生类的复用通常被称为白箱复用(white-box reuse)。术语“白箱”是相对可视性而言:在继承方式中,基类的内部细节对子类可见 。继承一定程度破坏了基类的封装,基类的改变,对派生类有很大的影响。派生类和基类间的依赖关系很强,耦合度高。
5. 对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组装或组合对象来获得。对象组合要求被组合的对象具有良好定义的接口。这种复用风格被称为黑箱复用(black-box reuse),因为对象的内部细节是不可见的。对象只以“黑箱”的形式出现。组合类之间没有很强的依赖关系,耦合度低。优先使用对象组合有助于你保持每个类被封装。
6.实际尽量多去用组合。组合的耦合度低,代码维护性好。不过继承也有用武之地的,有些关系就适合继承那就用继承,另外要实现多态,也必须要继承。类之间的关系可以用继承,可以用组合,就用组合。
上面就是継承的所有内容,希望铁子们可以有所收货
有几种方法:first_or_create_by、find_or_create_by等,它们的工作原理是:与数据库对话以尝试找到我们想要的东西如果我们找不到,就自己做保存到数据库显然,并发调用这些方法可能会使两个线程都找不到它们想要的东西,并且在第3步中一个线程会意外失败。似乎更好的解决方案是,创建或查找即:提前在您的数据库中创建合理的唯一性约束。如果你想保存一些东西,就保存它如果有效,那就太好了。如果它因为RecordNotUnique异常而无法工作,它已经存在,太好了,加载它那么在什么情况下我想使用Rails内置的东西而不是我自己的(看起来更可靠)create_or_find?
我正在尝试运行rakedb:create在DigitalOcean服务器上使用postgresql。但是,它返回错误Peerauthenticationfailedforuser"rails",引用config/database.yml登录凭据的存储位置奇怪的是,当我通过SSH登录服务器时,这些凭据以纯文本形式显示给我。我都试过了密码以纯文本形式显示给我,同样的事情发生了。环境在生产中,我必须手动强制执行,因为应用程序在启动时正在开发中并强制它在config/environments.rb中更改不工作。如果我不得不猜测,我可能会说环境中发生了一些有趣的事情,因为DigitalOcean
我在使用Ruby和OSXLion时遇到严重问题-每当我尝试启动Rails或什至是rake工具时,我都会收到此错误:[FATAL]failedtoallocatememory我尝试在不同版本(1.9.2-p180、1.9.2-p290、1.9.2-head)中重新编译ruby,但它总是一样。但是我注意到我可以删除一些gems,然后“rake”工具会起作用,只有“railss”会因该错误而死掉。似乎实际上没有足够的内存来容纳我正在使用的这么多gem,但这又一次看起来很奇怪——它在雪豹上工作得很好,甚至在我公司的macmini上和Lion上工作——唯一的区别是mini升级了SnowLeo
我在我的Rails4约会安排应用程序中遇到了几个错误,我似乎无法更正或找出根本原因。我的种子文件总是因众所周知的“错误,堆栈级别太深”而中断。但是当我运行我认为它正在中断的方法时,我得到了这个不同的错误:Seedingtimeslotsforworkdayno.1(0.5ms)SAVEPOINTactive_record_1(0.5ms)ROLLBACKTOSAVEPOINTactive_record_1fatal:exceptionreenteredfrom/Users/rskelley/.rvm/gems/ruby-2.0.0-p481/gems/activerecord-4.1.
我在我的JavaScript代码中使用委托(delegate)事件处理程序(jQuery),因此当单击动态添加的按钮时会发生一些事情。我想知道这是否存在性能缺陷?//Delegatedeventhandler$(document).on('click','#dynamicallyAddedButton',function(){console.log("Hello");});在性能方面,它与此相比如何?//Regulareventhandler$("#regularButton").on('click',function(){console.log("HelloAgain");});查看
当绑定(bind)到复选框输入的点击事件时,该复选框在我的事件处理程序运行时已经切换,更奇怪的是,如果我指定event.preventDefault();functionclicked(evt){alert(document.getElementById('foo').checked);evt.preventDefault();}document.getElementById('foo').addEventListener('click',clicked);[在chrome和firefox中测试]JSFiddleforthatcode警报将响应“true”(或复选框预单击的相反状态)。
当我学习bootstrap并尝试官方页面上的示例时,我发现了modal的一个缺陷(可能)零件。点击“Launchdemomodal”,你会注意到右上角有一个明显的空白,当模态对话框消失/出现时,导航栏会拉伸(stretch)/收缩。这是错误还是故意的?我觉得这很烦人,如何禁用它? 最佳答案 要手动修复这个问题,只需添加body.modal-open,.modal-open.navbar-fixed-top,.modal-open.navbar-fixed-bottom{margin-right:0px;}在Bootstrap样式表之
我正在寻找一种为iPhone压缩JavaScript代码的方法。有没有一种方法可以避免在小型且相当慢的设备上使用大量CPU时间? 最佳答案 使用YUICompressor 关于javascript-在没有性能缺陷的情况下打包JavaScript代码的最佳方法是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/114860/
我正在构建一个应用程序,并尝试使用“q”过滤器来使用API/tracks。这会查询SoundCloud并根据搜索词检索歌曲。很简单。我的问题:与soundcloud.com本身的搜索功能相比,使用/tracks似乎削弱了搜索功能。通过API获得的结果质量似乎要低得多,而直接在网站上搜索会返回高质量的结果。SoundCloud工程师可以对此发表评论吗? 最佳答案 确保您使用的是“a”参数而不是“查询”。SC.get('/tracks',{q:"keyword"},function(tracks){console.log(tracks)
随着网络的发展和普及,信息安全与每个人息息相关,包含方方面。每个人既是独立个体又必须和社会交换资源。这就需要把控一个尺度。要了解信息安全,首先需要对信息有个大体了解。从拥有者和使用者分类分为,个人,企业(个体工商户,集团,公司),国家(军事,银行),公共服务(医院,税务,公园)等。 信息安全从存储介质上分:移动存储(U盘,光盘,磁盘,硬盘,磁带),移动设备(手机,PDA,mini计算机,pad),计算机(个人计算机,企业个人电脑),内部服务器(fileweb,ftp,直播源),云存储(海康云,阿里云,百度云,金山云等),企业自建云,公司混合云,私有云 互联网应用的飞速发展和普及,网络安全越来越