⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 00000001.htm

📁 一份很好的linux入门资料
💻 HTM
📖 第 1 页 / 共 5 页
字号:
&nbsp;<BR>第二个方案中,可让卵形&nbsp;&quot;Oval&quot;&nbsp;类别有个&nbsp;&quot;setSize(size)&quot;:将&nbsp;&quot;width()&quot;&nbsp;和&nbsp;<BR>&quot;height()&quot;&nbsp;都设成&nbsp;&quot;size&quot;,然後让椭圆和圆形都自卵形中衍生出来。椭圆(而不是&nbsp;<BR>正圆形)会加入一个&nbsp;&quot;setSize(x,y)&quot;&nbsp;运算(如果这个&nbsp;&quot;setSize()&quot;&nbsp;运作行为的名&nbsp;<BR>称重复了,就得注意前面提过的「遮蔽效应」)。&nbsp;<BR>&nbsp;<BR>========================================&nbsp;<BR>&nbsp;<BR>Q62:对「圆形是/不是一种椭圆」这两难问题,有没有其他说法?&nbsp;<BR>&nbsp;<BR>如果你说:椭圆都可以不对称地挤压,又说:圆形是一种椭圆,又说:圆形不能不对&nbsp;<BR>称地挤压下去,那麽很明显的,你说过的某句话要做修正(老实说,该取消掉)。所&nbsp;<BR>以你不是得去掉&nbsp;&quot;Ellipse::setSize(x,y)&quot;,去掉圆形和椭圆间的继承关系,就是得&nbsp;<BR>承认你的「圆形」不一定是正圆。&nbsp;<BR>&nbsp;<BR>这儿有两个&nbsp;OO/C++&nbsp;新手最易落入的陷阱。他们想用程式小技巧来弥补差劲的事前设&nbsp;<BR>计(他们重新定义&nbsp;Circle::setSize(x,y),让它丢出一个例外,呼叫&nbsp;&quot;abort()&quot;&nbsp;,&nbsp;<BR>或是选用两参数的平均数,或是不做任何事情),不幸的,这些技俩都会让使用者感&nbsp;<BR>到吃惊:他们原本都预期&nbsp;&quot;width()&nbsp;==&nbsp;x&quot;&nbsp;和&nbsp;&quot;height()&nbsp;==&nbsp;y&quot;&nbsp;这两个事实会成立。&nbsp;<BR>&nbsp;<BR>唯一合理的做法似乎是:降低椭圆形&nbsp;&quot;setSize(x,y)&quot;&nbsp;的保证事项(譬如,你可以改&nbsp;<BR>成:「这运作行为“可能”会把&nbsp;width()&nbsp;设成&nbsp;x、height()&nbsp;设成&nbsp;y,也可能“不做&nbsp;<BR>任何事”」)。不幸的,这样会把界限冲淡,因为使用者没有任何有意义的物件行为&nbsp;<BR>足以依靠,整个类别阶层也就无毫价值可言了(很难说服别人去用一个:问你说它是&nbsp;<BR>做什麽的,你却只会耸耸肩膀说不知道的物件)。&nbsp;<BR>&nbsp;<BR>==========================&nbsp;<BR>●&nbsp;12C:继承--存取规则&nbsp;<BR>==========================&nbsp;<BR>&nbsp;<BR>Q63:为什麽衍生的类别无法存取基底的&nbsp;&quot;private&quot;&nbsp;东西?&nbsp;<BR>&nbsp;<BR>让你不被基底类别将来的改变所影响。&nbsp;<BR>&nbsp;<BR>衍生类别不能存取到基底的私有(private)成员,它有效地把衍生类别「封住」,&nbsp;<BR>基底类别内的私有成员如有改变,也不会影响到衍生的类别。&nbsp;<BR>&nbsp;<BR>========================================&nbsp;<BR>&nbsp;<BR>Q64:&quot;public:&quot;、&quot;private:&quot;、&quot;protected:&quot;&nbsp;的差别是?&nbsp;<BR>&nbsp;<BR>&quot;Private:&quot;&nbsp;在前几节中讨论过了;&quot;public:&quot;&nbsp;是指:「任何人都能存取之」;第三&nbsp;<BR>个&nbsp;&quot;protected:&quot;&nbsp;是让某成员(资料成员或是成员函数)只能由衍生类别存取之。&nbsp;<BR>&nbsp;<BR>【译注】&quot;protected:&quot;&nbsp;是让「衍生类别」,而非让「衍生类别的物件案例」能存取&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;得到&nbsp;protected&nbsp;的部份。&nbsp;<BR>&nbsp;<BR>========================================&nbsp;<BR>&nbsp;<BR>Q65:当我改变了内部的东西,怎样避免子类别被破坏?&nbsp;<BR>&nbsp;<BR>物件类别有两个不同的介面,提供给不同种类的用户:&nbsp;<BR>&nbsp;*&nbsp;&quot;public:&quot;&nbsp;介面用以服务不相关的类别。&nbsp;<BR>&nbsp;*&nbsp;&quot;protected:&quot;&nbsp;介面用以服务衍生的类别。&nbsp;<BR>&nbsp;<BR>除非你预期所有的子类别都会由你们的工作小组建出来,否则你应该将基底类别的资&nbsp;<BR>料位元内容放在&nbsp;&quot;private:&quot;&nbsp;处,用&nbsp;&quot;protected:&quot;&nbsp;行内存取函数来存取那些资料。&nbsp;<BR>这样的话,即使基底类别的私有资料改变了,衍生类别的程式也不会报废,除非你改&nbsp;<BR>变了基底类别的&nbsp;protected&nbsp;处的存取函数。&nbsp;<BR>&nbsp;<BR>================================&nbsp;<BR>●&nbsp;12D:继承--建构子与解构子&nbsp;<BR>================================&nbsp;<BR>&nbsp;<BR>Q66:若基底类别的建构子呼叫一个虚拟函数,为什麽衍生类别覆盖掉的那个虚拟函&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;数却不会被呼叫到?&nbsp;<BR>&nbsp;<BR>在基底类别&nbsp;Base&nbsp;的建构子执行过程中,该物件还不是属於衍生&nbsp;Derived&nbsp;的,所以&nbsp;<BR>如果&nbsp;&quot;Base::Base()&quot;&nbsp;呼叫了虚拟函数&nbsp;&quot;virt()&quot;,则&nbsp;&quot;Base::virt()&quot;&nbsp;会被呼叫,&nbsp;<BR>即使真的有&nbsp;&quot;Derived::virt()&quot;。&nbsp;<BR>&nbsp;<BR>类似的道理,当&nbsp;Base&nbsp;的解构子执行时,该物件不再是个&nbsp;Derived&nbsp;了,所以当&nbsp;<BR>Base::~Base()&nbsp;呼叫&nbsp;&quot;virt()&quot;,则&nbsp;&quot;Base::virt()&quot;&nbsp;会被执行,而非覆盖後的版本&nbsp;<BR>&quot;Derived::virt()&quot;。&nbsp;<BR>&nbsp;<BR>当你想像到:如果&nbsp;&quot;Derived::virt()&quot;&nbsp;碰得到&nbsp;Derived&nbsp;类别的物件成员,会造成什&nbsp;<BR>麽样的灾难,你很快就会看出这规则的明智之处。&nbsp;<BR>&nbsp;<BR>================================&nbsp;<BR>&nbsp;<BR>Q67:衍生类别的解构子应该外显地呼叫基底的解构子吗?&nbsp;<BR>&nbsp;<BR>不要,绝对不要外显地呼叫解构子(「绝对不要」指的是「几乎完全不要」)。&nbsp;<BR>&nbsp;<BR>衍生类别的解构子(不管你是否明显定义过)会“自动”去呼叫成员物件的、以及基&nbsp;<BR>底类别之子物件的解构子。成员物件会以它们在类别中出现的相反顺序解构,接下来&nbsp;<BR>是基底类别的子物件,以它们出现在类别基底列表的相反顺序解构之。&nbsp;<BR>&nbsp;<BR>只有在极为特殊的情况下,你才应外显地呼叫解构子,像是:解构一个由「新放入的&nbsp;<BR>new&nbsp;运算子」配置的物件。&nbsp;<BR>&nbsp;<BR>===========================================&nbsp;<BR>●&nbsp;12E:继承--Private&nbsp;与&nbsp;protected&nbsp;继承&nbsp;<BR>===========================================&nbsp;<BR>&nbsp;<BR>Q68:该怎麽表达出「私有继承」(private&nbsp;inheritance)?&nbsp;<BR>&nbsp;<BR>用&nbsp;&quot;:&nbsp;private&quot;&nbsp;来代替&nbsp;&quot;:&nbsp;public.&quot;&nbsp;&nbsp;譬如:&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class&nbsp;Foo&nbsp;:&nbsp;private&nbsp;Bar&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//...&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};&nbsp;<BR>&nbsp;<BR>================================&nbsp;<BR>&nbsp;<BR>Q69:「私有继承」和「成份」(composition)&nbsp;有多类似?&nbsp;<BR>&nbsp;<BR>私有继承是「成份」(has-a)&nbsp;的一种语法变形。&nbsp;<BR>&nbsp;<BR>譬如:「汽车有引擎」(&quot;car&nbsp;has-a&nbsp;engine&quot;)&nbsp;关系可用成份来表达:&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class&nbsp;Engine&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public:&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Engine(int&nbsp;numCylinders);&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;start();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//starts&nbsp;this&nbsp;Engine&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class&nbsp;Car&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public:&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Car()&nbsp;:&nbsp;e_(8)&nbsp;{&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//initializes&nbsp;this&nbsp;Car&nbsp;with&nbsp;8&nbsp;cylinders&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;start()&nbsp;{&nbsp;e_.start();&nbsp;}&nbsp;&nbsp;//start&nbsp;this&nbsp;Car&nbsp;by&nbsp;starting&nbsp;its&nbsp;engine&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private:&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Engine&nbsp;e_;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};&nbsp;<BR>&nbsp;<BR>同样的&nbsp;&quot;has-a&quot;&nbsp;关系也可用私有继承来表达:&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class&nbsp;Car&nbsp;:&nbsp;private&nbsp;Engine&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public:&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Car()&nbsp;:&nbsp;Engine(8)&nbsp;{&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//initializes&nbsp;this&nbsp;Car&nbsp;with&nbsp;8&nbsp;cylinders&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Engine::start;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//start&nbsp;this&nbsp;Car&nbsp;by&nbsp;starting&nbsp;its&nbsp;engine&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};&nbsp;<BR>&nbsp;<BR>这两种型式的成份有几分相似性:&nbsp;<BR>&nbsp;*&nbsp;这两种情况之下,Car&nbsp;只含有一个&nbsp;Engine&nbsp;成员物件。&nbsp;<BR>&nbsp;*&nbsp;两种情况都不能让(外界)使用者由&nbsp;Car*&nbsp;转换成&nbsp;Engine*&nbsp;。&nbsp;<BR>&nbsp;<BR>也有几个不同点:&nbsp;<BR>&nbsp;*&nbsp;如果你想要让每个&nbsp;Car&nbsp;都含有数个&nbsp;Engine&nbsp;的话,就得用第一个型式。&nbsp;<BR>&nbsp;*&nbsp;第二个型式可能会导致不必要的多重继承(multiple&nbsp;inheritance)。&nbsp;<BR>&nbsp;*&nbsp;第二个型式允许&nbsp;Car&nbsp;的成员从&nbsp;Car*&nbsp;转换成&nbsp;Engine*&nbsp;。&nbsp;<BR>&nbsp;*&nbsp;第二个型式可存取到基底类别的&nbsp;&quot;protected&quot;&nbsp;成员。&nbsp;<BR>&nbsp;*&nbsp;第二个型式允许&nbsp;Car&nbsp;覆盖掉&nbsp;Engine&nbsp;的虚拟函数。&nbsp;<BR>&nbsp;<BR>注意:私有继承通常是用来获得基底类别&nbsp;&quot;protected:&quot;&nbsp;成员的存取权力,但这通常&nbsp;<BR>只是个短程的解决方案。&nbsp;<BR>&nbsp;<BR>========================================&nbsp;<BR>&nbsp;<BR>Q70:我比较该用哪一种:成份还是私有继承?&nbsp;<BR>&nbsp;<BR>成份。&nbsp;<BR>&nbsp;<BR>正常情形下,你不希望存取到太多其他类别的内部,但私有继承会给你这些额外的权&nbsp;<BR>力(与责任)。不过私有继承不是洪水猛兽;它只是得多花心力去维护罢了,因为它&nbsp;<BR>增加了别人动到你的东西、让你的程式出差错的机会。&nbsp;<BR>&nbsp;<BR>合法而长程地使用私有继承的时机是:当你想新建一个&nbsp;Fred&nbsp;类别,它会用到&nbsp;Wilma&nbsp;<BR>类别的程式码,而且&nbsp;Wilma&nbsp;的程式码也会呼叫到你这个&nbsp;Fred&nbsp;类别里的运作行为时&nbsp;<BR>。这种情形之下,Fred&nbsp;呼叫了&nbsp;Wilma&nbsp;的非虚拟函数,Wilma&nbsp;也呼叫了它自己的、会&nbsp;<BR>被&nbsp;Fred&nbsp;所覆盖的虚拟函数(通常是纯虚拟函数)。要用成份来做的话,太难了。&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class&nbsp;Wilma&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protected:&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;fredCallsWilma()&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;cout&nbsp;&lt;&lt;&nbsp;&quot;Wilma::fredCallsWilma()\n&quot;;&nbsp;wilmaCallsFred();&nbsp;}&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;void&nbsp;wilmaCallsFred()&nbsp;=&nbsp;0;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};&nbsp;<BR>&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class&nbsp;Fred&nbsp;:&nbsp;private&nbsp;Wilma&nbsp;{&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public:&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;barney()&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;cout&nbsp;&lt;&lt;&nbsp;&quot;Fred::barney()\n&quot;;&nbsp;Wilma::fredCallsWilma();&nbsp;}&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protected:&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;virtual&nbsp;void&nbsp;wilmaCallsFred()&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;cout&nbsp;&lt;&lt;&nbsp;&quot;Fred::wilmaCallsFred()\n&quot;;&nbsp;}&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};&nbsp;<BR>&nbsp;<BR>========================================&nbsp;<BR>&nbsp;<BR>Q71:我应该用指标转型方法,把「私有」衍生类别转成它的基底吗?&nbsp;<BR>&nbsp;<BR>当然不该。&nbsp;<BR>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -