| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 7116 人关注过本帖, 9 人收藏
标题:[分享]c++综合技术应用文章合集^^
只看楼主 加入收藏
超级新人
Rank: 1
等 级:新手上路
帖 子:5
专家分:0
注 册:2007-3-21
收藏
得分:0 
谢谢了
2007-05-12 08:45
feitianyjx
Rank: 1
等 级:新手上路
帖 子:7
专家分:0
注 册:2007-5-10
收藏
得分:0 
好东东。。保存了。。。。。。。。。。。谢谢楼主。。。。。
2007-05-12 18:05
lifujun117
Rank: 1
等 级:新手上路
帖 子:11
专家分:0
注 册:2006-11-9
收藏
得分:0 
对我很有帮助,多谢版主分享。

2007-06-01 21:58
aipb2007
Rank: 8Rank: 8
来 自:CQU
等 级:贵宾
威 望:40
帖 子:2879
专家分:7
注 册:2007-3-18
收藏
得分:0 

////////////////////////////////////////原文////////////////////////////////////////////////////////////
Q: 我能防止别人从我的类继承吗?
A: 可以的,但何必呢?好吧,也许有两个理由:

出于效率考虑——不希望我的函数调用是虚的
出于安全考虑——确保我的类不被用作基类(这样我拷贝对象时就不用担心对象被切割(slicing)了)[译注:“对象切割”指,将派生类对象赋给基类变量时,根据C++的类型转换机制,只有包括在派生类中的基类部分被拷贝,其余部分被“切割”掉了。]
根据我的经验,“效率考虑”常常纯属多余。在C++中,虚函数调用如此之快,和普通函数调用并没有太多的区别。请注意,只有通过指针或者引用调用时才会启用虚拟机制;如果你指名道姓地调用一个对象,C++编译器会自动优化,去除任何的额外开销。
如果为了和“虚函数调用”说byebye,那么确实有给类继承体系“封顶”的需要。在设计前,不访先问问自己,这些函数为何要被设计成虚的。我确实见过这样的例子:性能要求苛刻的函数被设计成虚的,仅仅因为“我们习惯这样做”!

好了,无论如何,说了那么多,毕竟你只是想知道,为了某种合理的理由,你能不能防止别人继承你的类。答案是可以的。可惜,这里给出的解决之道不够干净利落。你不得不在在你的“封顶类”中虚拟继承一个无法构造的辅助基类。还是让例子来告诉我们一切吧:

class Usable;
class Usable_lock {
friend class Usable;
private:
Usable_lock() {}
Usable_lock(const Usable_lock&) {}
};
class Usable : public virtual Usable_lock {
// ...
public:
Usable();
Usable(char*);
// ...
};
Usable a;
class DD : public Usable { };
DD dd; // error: DD::DD() cannot access
// Usable_lock::Usable_lock(): private member

//////////////////////////////////////////////////////////////////////////////////////////////////////////

如果把
class Usable : public /*virtual*/ Usable_lock //虚继承Usable_lock类

这样,代码就可以通过,就没有达到防止Usable 被继承的作用。

////////////////////////////////////////////////////////////////////////////////
先说说上面的代码,包括继承原理:

首先,把我们不想被继承的类作为一个派生类去继承一个没哟意义的Usable_lock类,注意,这个类显示的把构造函数
声明为私有,然后把Usable作为友员类,这就是关键。
再来,继承中派生类创建的过程:首先要调用父类的构造函数,即先建立一个父类的对象。
这里Usable类是公有继承,所以是访问不到私有的构造函数,但是作为友员是可以的,所以消除了这个限制。由此,我们的Usable类是可以被创建的。

到这里,看看为什么普通的非虚拟继承,能使dd的创建合法。
首先,按照我们先前说讲,DD类公有继承Usable类,创建dd对象的过程是先调用父类构造函数(Usable类构造函数),这一步合法,因为可以访问到Usable的构造函数。这时就要创建一个Usable对象,要创建Usable 对象,就要调用Usable 的父类构造函数,就来到Usable_lock类,开始我们说了,由Usable访问Usable_lock是没有问题的。所以这样一来,dd对象就被正确的创建了。他间接的访问过Usable_lock。

////////////////////////////////////////////////////////////////////////
下面说说BJ在这个例子中是怎样通过虚拟技术防止Usable类被继承的:
虚拟继承,通过在声明派生类继承父类时加上virtual来指定。
虚拟继承的作用:当系统碰到多重继承的时候保证继承类成员函数的唯一性。
怎么理解他的作用,看下面这个图1:
class base //基类
class derive1 : public base
class derive2 : public base

class derive3 : public derive1,public derive2

这种情况下,derive3就同时拥有了两套base的函数。所以在调用时产生的模糊性会使程序出错。具体我就不谈那么多了。

解决这个问题,就用到了虚拟技术。
修改上面的代码 图2:
class base //基类
class derive1 : virtual public base
class derive2 : virtual public base

class derive3 : public derive1,public derive2

采用虚拟继承的时候,在derive3中,一旦一次继承了base类,再次继承base的时候就会忽略重复的base类。所以保证继承类成员函数的唯一性。

///////////////////////////////////////////////////////////////////
在这个问题中,BJ大师用到的不是这个原理,而是由此产生的一个构造函数调用顺序问题。
在非虚拟继承中,比如图1中。在构造derive3时,其父类调用顺序为derive1-derive2-base;
然后在虚拟继承中。比如图2中。在构造derive3时,其父类调用顺序为base-derive1-derive2;

同样,这样的顺序,作用显而易见,是防止base被多次继承。

再回到我们最初的话题,在DD类创建对象dd时,最先被调用的是Usable_lock类的构造函数,但是,由于Usable_lock构造函数声明被私有,就出现不能访问的错误。由此,是不能创建DD对象的。用这个方法,完成了防止了Usable被继承。


[此贴子已经被作者于2007-6-2 0:27:22编辑过]


Fight  to win  or  die...
2007-06-02 00:23
xujyule
Rank: 1
等 级:新手上路
帖 子:10
专家分:0
注 册:2007-6-11
收藏
得分:0 
复制下来到手机慢慢细读
2007-06-11 23:45
yuki
Rank: 2
等 级:新手上路
威 望:5
帖 子:508
专家分:0
注 册:2005-2-4
收藏
得分:0 

受益匪浅


我们都在命运湖上荡舟划桨,波浪起伏使我们无法逃离孤行;如果我们迷失方向,波浪将指引我们穿过另一天曙光
2007-08-24 09:22
blueboy82006
Rank: 5Rank: 5
来 自:幻想世界
等 级:贵宾
威 望:16
帖 子:1227
专家分:57
注 册:2007-7-23
收藏
得分:0 

感激涕零


2007-08-24 09:59
荒野的雄狮
Rank: 1
来 自:地球
等 级:新手上路
威 望:1
帖 子:300
专家分:0
注 册:2008-9-2
收藏
得分:0 
好贴啊,顶一个!
2008-10-19 19:51
快速回复:[分享]c++综合技术应用文章合集^^
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.023797 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved