推 dendrobium:1.use static member function to access 10/28 03:31
→ dendrobium:2.避免別人繼承你寫的東西以後就可以胡來 10/28 03:32
→ dendrobium:畢竟寫出來的東西 不一定只有自己會用 10/28 03:34
→ dendrobium:透過member function操作的好處是 永遠都在控制之中 10/28 03:35
推 dendrobium:2.我看錯了... 10/28 03:50
推 dendrobium:上面的2是在講4 10/28 04:03
→ QQ29:謝謝d大~ 觀念真的不好 應該說舉一反三的功力太差= = 10/28 04:07
> -------------------------------------------------------------------------- <
作者: LPH66 ((short)(-15074)) 看板: C_and_CPP
標題: Re: [問題] class繼承問題 請教
時間: Wed Oct 28 03:53:28 2009
※ 引述《QQ29 (我愛阿蓉)》之銘言:
: 和學弟討論繼承概念的時候 我亂想了一些case 測試
: 發現一些觀念的錯誤但又不太會解釋
: 1. 原本以為static data member 寫在private public裡面其實沒差
: 都不屬於class本身 <======這件事我是用
: (class A ;加上一個static int p; sizeof(A); 和去掉static int p在印出sizeof(A)
: 大小一樣,我認為他不屬於class本身.....)
: 所以外部都還是可以透過class name::去存取他
: 但是我發現我錯了 寫在private 外部無法用::去存取他
: 但是可以定義 <====這件事很怪 外面看不到卻可以定義?
你要稍微修正一下 static data member 的意義
static data member 是指這個 class 的所有 object 所共有的一個屬性值
因此 第一 既然是共有 自然不會在各個 object instance 裡出現
第二 既然是一個 class 裡只會有一份 那只好使用 class name:: 去存取
那麼 定成 public/private 的差別就在於這個屬性值我要不要其他人看到
總是會有一些屬性值內部需要用 全部只要一份 但不想給外面看的
這些就會是 private static member
: 2. private方式繼承老爸 可是變成老爸的東西我完全無法呼叫
: 那繼承幹嘛??? 有什麼用意.........
不是我無法呼叫
而是外面不能透過我去呼叫老爸的東西
例如:
class A {
public:
void f(){}
};
class B : private a
{
public:
void g(){f();}
};
那在其他地方如果有一個 B b;
則 b.g(); 是OK的 但 b.f(); 是不行的
(順帶一提, 似乎是為了防止 polymorphism 呼叫的關係,
此例中 B* 到 A* 的轉換似乎是不會允許的...)
用意也許是想在父 class 之外提供一些功能
但因為父 class 有些功能可能影響我的工作
於是只好把繼承來的父 class 的 method 設成 private
: 3.另外我自己對protected 作的白話解釋
: 你要給兒子
: 就只好寫成protected
: 兒子就多了老爸的protected的東西
: protected 要用也是要透過 member function
: 對老爸來講 其實也是private的行為 只是多了可以給兒子繼承這個特性
: 以上有錯誤嘛?
大致是正確的
: 4.有個不解的地方是 老爸的private資料明明就繼承給兒子
: 兒子看的到卻不能用 頂多透過 老爸的function去修改數值
: 然後要get時 再透過老爸的get function去get...
: 這樣為啥不直接老爸就寫成protected就好
: 有沒有什麼case是老爸必定要寫private 不然會有什麼漏洞或是什麼問題產生?
我的東西我不想給兒子亂動 (因為我有我的東西的擺放規則)
但我希望我兒子可以拿去參考
那麼我只好要求兒子想要時要來找我拿 (getter)
想改時也要我看一下 (setter) 才准改
: 以上四點 是我和學弟討論遇到的小小問題
: 請各位指教
: 謝謝
--
実琴:「河野!你真的就這樣被物質慾望給吸引過去了嗎?!」
亨:「只要穿著女裝擺出親切的樣子,所有必要花費就能全免,似乎一點都不壞啊。」
実琴:「難道你沒有男人的尊嚴了嗎?!」
亨:(斷然道)「沒有。在節衣縮食且生活吃緊的學生面前,沒有那種東西。」
--プリンセス・プリンセス 第二話
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.30.84
推 QQ29:L大我對於2. 想問 如果f()寫在private 為啥就不能透過g呼叫了 10/28 04:03
→ QQ29:我認知是 private繼承 所有老爸的東西都會壓成private 10/28 04:04
→ QQ29:所以都不能用?原本是這樣認為但是似乎原本老爸是public 10/28 04:05
→ QQ29:或是老爸本身是protected的話 private繼承後 兒子要存取的行 10/28 04:05
→ QQ29:為都是要變成 L大舉的 利用g去呼叫f... 10/28 04:05
> -------------------------------------------------------------------------- <
作者: QQ29 (我愛阿蓉) 看板: C_and_CPP
標題: Re: [問題] class繼承問題 請教
時間: Wed Oct 28 04:15:13 2009
※ 引述《LPH66 ((short)(-15074))》之銘言:
: ※ 引述《QQ29 (我愛阿蓉)》之銘言:
: : 2. private方式繼承老爸 可是變成老爸的東西我完全無法呼叫
: : 那繼承幹嘛??? 有什麼用意.........
: 不是我無法呼叫
: 而是外面不能透過我去呼叫老爸的東西
: 例如:
: class A {
: public:
: void f(){}
: };
: class B : private a
: {
: public:
: void g(){f();}
: };
: 那在其他地方如果有一個 B b;
: 則 b.g(); 是OK的 但 b.f(); 是不行的
: (順帶一提, 似乎是為了防止 polymorphism 呼叫的關係,
: 此例中 B* 到 A* 的轉換似乎是不會允許的...)
: 用意也許是想在父 class 之外提供一些功能
: 但因為父 class 有些功能可能影響我的工作
: 於是只好把繼承來的父 class 的 method 設成 private
你好L大 針對這問題我有個盲點
http://0rz.tw/9d2H8 之前看那種有個繼承表格 或是這網頁
他竟然寫老爸private的話就不繼承了
不過我認為他寫錯了
因為我不管怎麼樣改老爸的 sizeof(兒子) 大小都不變
應該都有繼承到
但是盲點在於
L大這例子b.g() 可以呼叫到f()
那要是f()改為 private之下變成無法呼叫
而之前看資料 有那個繼承表
原本老爸public 透過private繼承 會壓成 private
和原本 老爸private 透過private繼承 也是壓成 private
但這裡說的private 似乎對於兒子來講 一個可用一個不可用.......
讓我非常的疑惑
目前結論是
原本是 private,繼承之後兒子也不能使用
原本public 壓成 private,兒子可以用,可是外面的人不能,孫子也不能
那對兒子來說兩個管道都是private 差別在哪? 我如果要解釋該怎麼講
之前認知就是 "壓"
以繼承角度看 是哪種方式繼承
就"壓"
如果還是private狀態就是兒子不准用<===結論是錯的
以前上課傻傻的沒想那麼多 反正老爸private兒子就沒得用 要用就要老爸寫protected
現在發現這問題
請大大給予指教
謝謝
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.113.207.187
※ 編輯: QQ29 來自: 140.113.207.187 (10/28 04:18)
※ 編輯: QQ29 來自: 140.113.207.187 (10/28 04:22)
> -------------------------------------------------------------------------- <
作者: tinlans ( ) 看板: C_and_CPP
標題: Re: [問題] class繼承問題 請教
時間: Wed Oct 28 07:23:10 2009
※ 引述《QQ29 (我愛阿蓉)》之銘言:
: 4.有個不解的地方是 老爸的private資料明明就繼承給兒子
: 兒子看的到卻不能用 頂多透過 老爸的function去修改數值
: 然後要get時 再透過老爸的get function去get...
: 這樣為啥不直接老爸就寫成protected就好
: 有沒有什麼case是老爸必定要寫private 不然會有什麼漏洞或是什麼問題產生?
基本上 OO 程式的原則,
就是所有 data members 都要是 private,
想開放給兒子去存取是把 setter/getter 標成 protected,
不准兒子存取就是連這兩樣都 private 掉甚至是不提供,
這單純只是類別的封裝概念而已,
所以為了符合這種概念都會把 data members 直接 private 起來。
如果你不想探討概念性的東西,
真的是有必要的例子也很好找,
像是你為了加快程式速度可能會寫類似這樣的東西:
class MyClass {
public:
...
ResultT query() const;
private:
...
mutable ResultT cache_;
mutable bool initialized_;
};
ResultT MyClass::query() const
{
if(initialized_) return cache_;
else {
cache_ = ...;
initialized_ = true;
return cache_;
}
}
只要這個 query method 被執行過一次,
那就能快速的取得結果,
被執行過一次的狀態用 initialized_ 這個 data member 去記錄,
之前算出來的結果暫存在 cache_ 這個 data member,
一般來說你絕對不會希望 initialized_ 這種東西被兒子隨便修改吧?
--
Ling-hua Tseng (uranus@tinlans.org)
Department of Computer Science, National Tsing-Hua University
Interesting: C++, Compiler, PL/PD, OS, VM, Large-scale software design
Researching: Software pipelining for VLIW architectures
Homepage: https://www.tinlans.org
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 118.160.115.152
※ 編輯: tinlans 來自: 118.160.115.152 (10/28 07:25)
推 VictorTom:推....:) 10/28 09:21
> -------------------------------------------------------------------------- <
作者: littleshan (我要加入劍道社!) 看板: C_and_CPP
標題: Re: [問題] class繼承問題 請教
時間: Wed Oct 28 10:20:09 2009
※ 引述《QQ29 (我愛阿蓉)》之銘言:
: 你好L大 針對這問題我有個盲點
: http://0rz.tw/9d2H8 之前看那種有個繼承表格 或是這網頁
: 他竟然寫老爸private的話就不繼承了
: 不過我認為他寫錯了
: 因為我不管怎麼樣改老爸的 sizeof(兒子) 大小都不變
: 應該都有繼承到
: 但是盲點在於
: L大這例子b.g() 可以呼叫到f()
: 那要是f()改為 private之下變成無法呼叫
: 而之前看資料 有那個繼承表
: 原本老爸public 透過private繼承 會壓成 private
: 和原本 老爸private 透過private繼承 也是壓成 private
: 但這裡說的private 似乎對於兒子來講 一個可用一個不可用.......
: 讓我非常的疑惑
嗯 許多 C++ 的教學書籍都會寫這個表格
但這個表格呢 其實是很容易誤導人的
而且它完全沒有寫出 private/protected 繼承的目的
private 繼承和 protected 繼承的原理
其實非常簡單
比如說以下的 code
class Base {
public:
void foo();
};
class Derived : private Base {
public:
void bar()
{
foo(); // 呼叫 Base::foo()
}
};
compiler 會把它轉成這個樣子...
class Derived {
private:
Base base_;
public:
void bar()
{
base_.foo();
}
};
也就是說呢
private 繼承其實不過就是在子類別中
放入一個父類別的物件
並且把它設定為 private
而 protected 繼承也是一樣的:在子類別中加一個父類別的物件
並且設定為 protected
不過在使用 private/protected 繼承時
compiler 動了一點小手腳
使得子類別可以呼叫父類別的 protected 成員函式
(如果你不用繼承而是自己加一個物件 是無法呼叫 protected 函式的)
這是使用 private/protected 繼承
與「直接包一個物件進來」的不同之處
那麼 private/protected 繼承要用在什麼時候?
其實大部份的情況下 private/protected 繼承都可以用物件包物件的方法來取代
(這種寫法也比較容易讓其它人理解 也比較有彈性)
但如果你還想呼叫 protected member function
那就必須要繼承了
請參考 Effective C++ 還有 Exceptional C++
這兩本書都有談到 private 繼承
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.29.108
推 twotwoone:寫得很好,推。 10/28 10:28
推 VictorTom:再推:) 10/28 10:50
> -------------------------------------------------------------------------- <
作者: QQ29 (我愛阿蓉) 看板: C_and_CPP
標題: Re: [問題] class繼承問題 請教
時間: Wed Oct 28 14:57:26 2009
※ 引述《littleshan (我要加入劍道社!)》之銘言:
: ※ 引述《QQ29 (我愛阿蓉)》之銘言:
謝謝l大的解說 不過請容我再對以下提出一些問題....
: 比如說以下的 code
: class Base {
: public:
: void foo();
: };
: class Derived : private Base {
: public:
: void bar()
: {
: foo(); // 呼叫 Base::foo()
: }
: };
: compiler 會把它轉成這個樣子...
: class Derived {
: private:
: Base base_;
: public:
: void bar()
: {
: base_.foo();
: }
: };
: 也就是說呢
: private 繼承其實不過就是在子類別中
: 放入一個父類別的物件
: 並且把它設定為 private
: 而 protected 繼承也是一樣的:在子類別中加一個父類別的物件
: 並且設定為 protected
: 不過在使用 private/protected 繼承時
: compiler 動了一點小手腳
: 使得子類別可以呼叫父類別的 protected 成員函式
: (如果你不用繼承而是自己加一個物件 是無法呼叫 protected 函式的)
: 這是使用 private/protected 繼承
: 與「直接包一個物件進來」的不同之處
: 那麼 private/protected 繼承要用在什麼時候?
: 其實大部份的情況下 private/protected 繼承都可以用物件包物件的方法來取代
若是以兒子來看
protected繼承 就l大所講的 其實多了一個protected: Base base_;
base_.能夠存取的範圍 就老爸的protected 和public
private繼承 多了個 private: Base base_;
base_.能去存取的範圍 就也是老爸的protected和public
所以對兒子 能夠存取的行為來講 要用老爸的 都還是要兒子自己member function
間接的去存取老爸
所以我自認為 對兒子來講 這兩種繼承方式 造成兒子 一樣的權限
差別在於 如果這兒子有了孫子(public繼承兒子)
孫子還是可以"多"得到 兒子(protected繼承後 多產生的Base base_:)
讓孫子可以去呼叫 super class...
若兒子是用private繼承
孫子得到的Base base_ 是private的..... 所以他根本始用不了
所以就失去 呼叫super class的能力
不知道以上我的結論是否有錯誤
請給予指點
謝謝各位
: (這種寫法也比較容易讓其它人理解 也比較有彈性)
: 但如果你還想呼叫 protected member function
: 那就必須要繼承了
: 請參考 Effective C++ 還有 Exceptional C++
: 這兩本書都有談到 private 繼承
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.113.207.187
推 littleshan:You got it! 10/28 16:10
→ littleshan:protected 的目的就是「不讓外界用,但要給兒子用」 10/28 16:11
→ littleshan:不管這個關鍵字出現在哪,它的概念都是一樣的 10/28 16:11