| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 6322 人关注过本帖
标题:推荐:C++语言常见问题解答
取消只看楼主 加入收藏
yuyunliuhen
Rank: 6Rank: 6
等 级:贵宾
威 望:20
帖 子:1435
专家分:0
注 册:2005-12-12
收藏
得分:0 
"public:"、"private:"、"protected:" 的差别是? 
 
"Private:" 在前几节中讨论过了;"public:" 是指:「任何人都能存取之」;第三 
个 "protected:" 是让某成员(资料成员或是成员函数)只能由衍生类别存取之。 
 
【译注】"protected:" 是让「衍生类别」,而非让「衍生类别的物件案例」能存取 
         得到 protected 的部份。

Go confidently in the  directions of your dreams,live the life you have imagined!Just do it!
It is no use learning without thinking!
2006-12-23 22:39
yuyunliuhen
Rank: 6Rank: 6
等 级:贵宾
威 望:20
帖 子:1435
专家分:0
注 册:2005-12-12
收藏
得分:0 
当我改变了内部的东西,怎样避免子类别被破坏? 
 
物件类别有两个不同的介面,提供给不同种类的用户: 
  * "public:" 介面用以服务不相关的类别。 
  * "protected:" 介面用以服务衍生的类别。 
 
除非你预期所有的子类别都会由你们的工作小组建出来,否则你应该将基底类别的资 
料位元内容放在 "private:" 处,用 "protected:" 行内存取函数来存取那些资料。 
这样的话,即使基底类别的私有资料改变了,衍生类别的程式也不会报废,除非你改 
变了基底类别的 protected 处的存取函数。

Go confidently in the  directions of your dreams,live the life you have imagined!Just do it!
It is no use learning without thinking!
2006-12-23 22:39
yuyunliuhen
Rank: 6Rank: 6
等 级:贵宾
威 望:20
帖 子:1435
专家分:0
注 册:2005-12-12
收藏
得分:0 
若基底类别的建构子呼叫一个虚拟函数,为什麽衍生类别覆盖掉的那个虚拟函 
      数却不会被呼叫到? 
 
在基底类别 Base 的建构子执行过程中,该物件还不是属於衍生 Derived 的,所以 
如果 "Base::Base()" 呼叫了虚拟函数 "virt()",则 "Base::virt()" 会被呼叫, 
即使真的有 "Derived::virt()"。 
 
类似的道理,当 Base 的解构子执行时,该物件不再是个 Derived 了,所以当 
Base::~Base() 呼叫 "virt()",则 "Base::virt()" 会被执行,而非覆盖後的版本 
"Derived::virt()"。 
 
当你想像到:如果 "Derived::virt()" 碰得到 Derived 类别的物件成员,会造成什 
麽样的灾难,你很快就会看出这规则的明智之处。

Go confidently in the  directions of your dreams,live the life you have imagined!Just do it!
It is no use learning without thinking!
2006-12-23 22:39
yuyunliuhen
Rank: 6Rank: 6
等 级:贵宾
威 望:20
帖 子:1435
专家分:0
注 册:2005-12-12
收藏
得分:0 
衍生类别的解构子应该外显地呼叫基底的解构子吗? 
 
不要,绝对不要外显地呼叫解构子(「绝对不要」指的是「几乎完全不要」)。 
 
衍生类别的解构子(不管你是否明显定义过)会“自动”去呼叫成员物件的、以及基 
底类别之子物件的解构子。成员物件会以它们在类别中出现的相反顺序解构,接下来 
是基底类别的子物件,以它们出现在类别基底列表的相反顺序解构之。 
 
只有在极为特殊的情况下,你才应外显地呼叫解构子,像是:解构一个由「新放入的 
new 运算子」配置的物件。

Go confidently in the  directions of your dreams,live the life you have imagined!Just do it!
It is no use learning without thinking!
2006-12-23 22:39
yuyunliuhen
Rank: 6Rank: 6
等 级:贵宾
威 望:20
帖 子:1435
专家分:0
注 册:2005-12-12
收藏
得分:0 
该怎麽表达出「私有继承」(private inheritance)? 
 
用 ": private" 来代替 ": public."  譬如: 
 
         class Foo : private Bar { 
           //... 
         }; 

Go confidently in the  directions of your dreams,live the life you have imagined!Just do it!
It is no use learning without thinking!
2006-12-23 22:40
yuyunliuhen
Rank: 6Rank: 6
等 级:贵宾
威 望:20
帖 子:1435
专家分:0
注 册:2005-12-12
收藏
得分:0 
「私有继承」和「成份」(composition) 有多类似? 
 
私有继承是「成份」(has-a) 的一种语法变形。 
 
譬如:「汽车有引擎」("car has-a engine") 关系可用成份来表达: 
 
         class Engine { 
         public: 
           Engine(int numCylinders); 
           void start();                 //starts this Engine 
         }; 
 
         class Car { 
         public: 
           Car() : e_(8) { }             //initializes this Car with 8 cylinders 
           void start() { e_.start(); }  //start this Car by starting its engine 
         private: 
           Engine e_; 
         }; 
 
同样的 "has-a" 关系也可用私有继承来表达: 
 
         class Car : private Engine { 
         public: 
           Car() : Engine(8) { }         //initializes this Car with 8 cylinders 
           Engine::start;                //start this Car by starting its engine 
         }; 
 
这两种型式的成份有几分相似性: 
  * 这两种情况之下,Car 只含有一个 Engine 成员物件。 
  * 两种情况都不能让(外界)使用者由 Car* 转换成 Engine* 。 
 
也有几个不同点: 
  * 如果你想要让每个 Car 都含有数个 Engine 的话,就得用第一个型式。 
  * 第二个型式可能会导致不必要的多重继承(multiple inheritance)。 
  * 第二个型式允许 Car 的成员从 Car* 转换成 Engine* 。 
  * 第二个型式可存取到基底类别的 "protected" 成员。 
  * 第二个型式允许 Car 覆盖掉 Engine 的虚拟函数。 
 
注意:私有继承通常是用来获得基底类别 "protected:" 成员的存取权力,但这通常 
只是个短程的解决方案。 

Go confidently in the  directions of your dreams,live the life you have imagined!Just do it!
It is no use learning without thinking!
2006-12-23 22:40
yuyunliuhen
Rank: 6Rank: 6
等 级:贵宾
威 望:20
帖 子:1435
专家分:0
注 册:2005-12-12
收藏
得分:0 
我比较该用哪一种:成份还是私有继承? 
 
成份。 
 
正常情形下,你不希望存取到太多其他类别的内部,但私有继承会给你这些额外的权 
力(与责任)。不过私有继承不是洪水猛兽;它只是得多花心力去维护罢了,因为它 
增加了别人动到你的东西、让你的程式出差错的机会。 
 
合法而长程地使用私有继承的时机是:当你想新建一个 Fred 类别,它会用到 Wilma 
类别的程式码,而且 Wilma 的程式码也会呼叫到你这个 Fred 类别里的运作行为时 
。这种情形之下,Fred 呼叫了 Wilma 的非虚拟函数,Wilma 也呼叫了它自己的、会 
被 Fred 所覆盖的虚拟函数(通常是纯虚拟函数)。要用成份来做的话,太难了。 
 
         class Wilma { 
         protected: 
           void fredCallsWilma() 
             { cout << "Wilma::fredCallsWilma()\n"; wilmaCallsFred(); } 
           virtual void wilmaCallsFred() = 0; 
         }; 
 
         class Fred : private Wilma { 
         public: 
           void barney() 
             { cout << "Fred::barney()\n"; Wilma::fredCallsWilma(); } 
         protected: 
           virtual void wilmaCallsFred() 
             { cout << "Fred::wilmaCallsFred()\n"; } 
         }; 

Go confidently in the  directions of your dreams,live the life you have imagined!Just do it!
It is no use learning without thinking!
2006-12-23 22:40
yuyunliuhen
Rank: 6Rank: 6
等 级:贵宾
威 望:20
帖 子:1435
专家分:0
注 册:2005-12-12
收藏
得分:0 
我应该用指标转型方法,把「私有」衍生类别转成它的基底吗? 
 
当然不该。 
 
以私有衍生类别的运作行为、夥伴来看,从它上溯到基底类别的关系为已知的,所以 
从 PrivatelyDer* 往上转换成 Base*(或是从 PrivatelyDer& 到 Base&)是安全的 
;强制转型是不需要也不鼓励的。 
 
然而用 PrivateDer 的人应该避免这种不安全的转换,因为此乃立足於 PrivateDer 
的 "private" 决定,这个决定很容易在日後不经察觉就改变了。 
 

Go confidently in the  directions of your dreams,live the life you have imagined!Just do it!
It is no use learning without thinking!
2006-12-23 22:40
yuyunliuhen
Rank: 6Rank: 6
等 级:贵宾
威 望:20
帖 子:1435
专家分:0
注 册:2005-12-12
收藏
得分:0 
保护继承 (protected inheritance) 和私有继承有何关连? 
 
相似处:两者都能覆盖掉私有/保护基底类别的虚拟函数,两者都不把衍生的类别视 
为“一种”基底类别。 
 
不相似处:保护继承可让衍生类别的衍生类别知道它的继承关系(把实行细节显现出 
来)。它有好处(允许保护继承类别的子类别,藉这项关系来使用保护基底类别), 
也有代价(保护继承的类别,无法既想改变这种关系,而又不破坏到进一步的衍生类 
别)。 
 
保护继承使用 ": protected" 这种语法: 
 
         class Car : protected Engine { 
           //... 
         }; 

Go confidently in the  directions of your dreams,live the life you have imagined!Just do it!
It is no use learning without thinking!
2006-12-23 22:41
yuyunliuhen
Rank: 6Rank: 6
等 级:贵宾
威 望:20
帖 子:1435
专家分:0
注 册:2005-12-12
收藏
得分:0 
"private" 和 "protected" 的存取规则是什麽? 
 
拿底下这些类别当例子: 
 
         class B                    { /*...*/ }; 
         class D_priv : private   B { /*...*/ }; 
         class D_prot : protected B { /*...*/ }; 
         class D_publ : public    B { /*...*/ }; 
         class UserClass            { B b; /*...*/ }; 
 
没有一个子类别能存取到 B 的 private 部份。 
在 D_priv 内,B 的 public 和 protected 部份都变成 "private"。 
在 D_prot 内,B 的 public 和 protected 部份都变成 "protected"。 
在 D_publ 内,B 的 public 部份还是 public,protected 还是 protected 
  (D_publ is-a-kind-of-a B) 。 
Class "UserClass" 只能存取 B 的 public 部份,也就是:把 UserClass 从 B 那 
儿封起来了。 
 
欲把 B 的 public 成员在 D_priv 或 D_prot 内也变成 public,只要在该成员的名 
字前面加上 "B::"。譬如:想让 "B::f(int,float)" 成员在 D_prot 内也是 public 
的话,照这样写: 
 
         class D_prot : protected B { 
         public: 
           B::f;    //注意:不是写成 "B::f(int,float)" 
         }; 
 

Go confidently in the  directions of your dreams,live the life you have imagined!Just do it!
It is no use learning without thinking!
2006-12-23 22:41
快速回复:推荐:C++语言常见问题解答
数据加载中...
 
   



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

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