Re: [問題] c++ 的物件使用一問
......先行聲明,以下內容大多出自於猜測
如有錯誤希望大家可以出聲指正,以免造成誤導與混淆 :(
: ========================
: 你的問題其實只有一個關鍵:
: ic::ic(src& s)
: 接受的是 non-const reference
: 你傳暫時物件進去,那就等於傳 const 物件了,這樣當然會錯囉
: 否則你可以試試把 ic(src& s) 參數改成 const src &s 看看
: 就可以運作了
: 函式的 reference 參數
: 如果沒加 const,就表示接收進來的物件可能被修改
: 所以如果有傳入暫時物件的可能,一定要加 const
: ==========
我覺得不太像是這個問題,我寫幾個測試 code
根據原 po 的問題改編,g++ 3.4.2 得錯誤訊息
error: no matching function for call to
`DerivedA::DerivedA(Derived A(&)(DerivedB))'
note: candidates are: DerivedA::DerivedA(const DerivedA&)
note: DerivedA::DerivedA(const Base&)
struct Base{Base(){}};
struct DerivedA: public Base{
DerivedA(const Base&){}
DerivedA(const DerivedA&){}
};
struct DerivedB: public Base{
DerivedB(){}
DerivedB(const Base&){}
};
int main(){
DerivedA a(Base());
DerivedA b(DerivedB(a));
DerivedA c(b); // at this line
}
b 是一個普通的 DerivedA 物件,可是 const DerivedA& 和 const Base& 都不吃
根據錯誤訊息,b 的型別是 Derived A(&)(DerivedB)
再來看 Comeau C++ 4.3.3 的錯誤訊息:
(from: http://www.comeaucomputing.com/tryitout/)
(btw, 我好想買喔)
error: no instance of constructor "DerivedA::DerivedA"
matches the argument list
The argument types that you used are: (DerivedA (DerivedB))
DerivedA c(b);
^
也就是說,他認為 b 的型別是 DerivedA (DerivedB) 了
把上述 code 做一點修正:
把 struct DerivedA 移到 DerivedB 下面
在 DerivedA 裡追加一個 c'tor 叫
DerivedA(const DerivedA(DerivedB)){}
(模仿 Comeau 的型別)
在 g++ 下,再得錯誤訊息:(我只列改變)
note: candidates are:
DerivedA::DerivedA(const DerivedA(*)(DerivedB)) <near match>
...
看到 g++ 的提示,near match...(差一個 const)
而 Comeau 的 compile 結果呢?
很抱歉,還是 error, 不過給的錯誤訊息沒有任何改變
(這點就覺得 g++ 錯誤訊息比較方便了…
有時候看不懂的型別就 compile 沒差,反正會告訴你)
再改一次,這次加個 &
DerivedA(const DerivedA& (DerivedB)){}
錯誤訊息:
note: candidates are:
DerivedA::DerivedA(const DerivedA&(*)(DerivedB)) <near match>
...
這次改成 g++ 的提示:
DerivedA(const DerivedA(&)(DerivedB)){}
這樣…還是不能通過編譯
note: candidates are:
DerivedA::DerivedA(const DerivedA(&)(DerivedB))
...
這次連 <near match> 都沒給了
把 const 拿掉,變成:
DerivedA(DerivedA(&)(DerivedB)){}
這下終於順利通過 compile 了,g++ 和 comeau 都一樣
而如果改成這樣:
DerivedA(DerivedA(DerivedB)){}
其實也可以通過編譯,同樣 g++ 和 comeau 都一樣
這樣也可以:
DerivedA(DerivedA(*)(DerivedB)){}
ok, 回頭去看其中一個型別:
typeA(*)(typeB)
不覺得很像 function pointer 嗎?
那麼 typeA(&)(typeB) 又是什麼?
答案是實體 function...(我居然測試測半天才發現這個事實)
請再回到最早的 code, 並在最下面加上這個:
Base base;
b(base);
b(Base());
得 g++ 錯誤訊息
undefined reference to `b(DerivedB)'
undefined reference to `b(DerivedB)'
comeau c++... online 版沒有 link, 所以沒有錯誤 :Q
ok, 說得亂七八糟,講個結論吧
...嗯,剛剛本來想舉些例子做結論
不過舉了幾個例子之後又發現一些奇妙的東西
比方說
int value = 5;
TypeA a(TypeB(value));
或
const int value = 5;
TypeA a(TypeB(value));
則 a 是一個 function
TypeA a(TypeB(5));
則 a 是一個 TypeA 物件,用 TypeB::TypeB(int) 建立的暫時物件建立的物件
我被這搞糊塗了...
不過看來假使我這樣寫:
int(int)
則這代表型別:
int(*)(int)
或
int(&)(int)
我想這也是為什麼 boost::function<int(int)> 可以這樣用了
另外 g++ 有時候也會將 int(int) 視為 int(&)(int)
我想這可能是最佳化機制的緣故…(純猜測)
(昏倒, C++ 好謎... 避免使用這種弔詭的用法吧)
(畢竟平時應該不會用暫時物件來建立物件吧)
(再鑽研下去似乎過於沒意義了)
--
By Gamers, For Gamers - from the past Interplay
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.132.128.238
※ 編輯: godfat 來自: 220.132.128.238 (02/09 04:27)
討論串 (同標題文章)
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章