re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-17 20:54
@visualfc
Qt Creator我知道,Qt Creator的cplusplus是指的什么?
Qt Creator的自動完成功能嗎?
我看過你的一些作品,果然對這方面的東西了解很多~_~
@陳梓瀚(vczh)
其實我的需求上面也有說…… 就是將代碼染染色……
不然直接在blog上貼代碼太丑陋了……
Qt Creator我知道,Qt Creator的cplusplus是指的什么?
Qt Creator的自動完成功能嗎?
我看過你的一些作品,果然對這方面的東西了解很多~_~
@陳梓瀚(vczh)
其實我的需求上面也有說…… 就是將代碼染染色……
不然直接在blog上貼代碼太丑陋了……
re: XL Library Preview,誠征指點 OwnWaterloo 2009-11-17 20:21
@溪流
某人犯傻去繼承string,那是他的責(zé)任。
沒有必要為了避免他的錯誤,讓所有人讓步,承受虛指針的開銷。
反向迭代器,我猜的也是這么回時。
不過具體沒看。
去看看代碼吧,應(yīng)該不多。
可能會有一些細(xì)節(jié),大致想的時候會被忽略。
某人犯傻去繼承string,那是他的責(zé)任。
沒有必要為了避免他的錯誤,讓所有人讓步,承受虛指針的開銷。
反向迭代器,我猜的也是這么回時。
不過具體沒看。
去看看代碼吧,應(yīng)該不多。
可能會有一些細(xì)節(jié),大致想的時候會被忽略。
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 22:01
@空明流轉(zhuǎn)
好東西啊,好東西,看得我心花怒放~_~
再次感謝~_~
順便也感謝一下cexer。
果然是【閱盡MFC,WTL,SmartWin++,win32gui,jlib2 ,VCF ;看盡天下 GUI 的感覺。】
果然只看示例和書不寫代碼是不行的。就書上的示例代碼,我還領(lǐng)會不了其精髓……
其實也不是我不想寫…… 我寫過一些……
然后就沒機會寫了……
好東西啊,好東西,看得我心花怒放~_~
再次感謝~_~
順便也感謝一下cexer。
果然是【閱盡MFC,WTL,SmartWin++,win32gui,jlib2 ,VCF ;看盡天下 GUI 的感覺。】
果然只看示例和書不寫代碼是不行的。就書上的示例代碼,我還領(lǐng)會不了其精髓……
其實也不是我不想寫…… 我寫過一些……
然后就沒機會寫了……
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 21:47
@空明流轉(zhuǎn)
我靠!還有這種工具!
太感謝了~_~
其實我也不做什么的啦……
主要是寫文檔(設(shè)計文檔、博客)的時候染染色啦……
我靠!還有這種工具!
太感謝了~_~
其實我也不做什么的啦……
主要是寫文檔(設(shè)計文檔、博客)的時候染染色啦……
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 21:27
@陳梓瀚(vczh)
【子類不需要非得實現(xiàn)什么,純粹是模擬非純虛函數(shù)。因為父類必須提供所有可以覆蓋的界面的空實現(xiàn),才可以讓實現(xiàn)控件的人,只寫他們關(guān)心的東西。】
上面已經(jīng)說明了:
"父類提供所有可以覆蓋的界面的空實現(xiàn)",或者說默認(rèn)實現(xiàn),并讓實現(xiàn)控件的人,只寫他們關(guān)心的東西 —— 這不需要ATL-style式的繼承,普通繼承就可以了。
只有在"向子類要求一些莫須有的東西"時,才需要依靠template。
【我重寫VL++的目的就是想提供一個用來分析字符串(速度不用爆快,但肯定要好用)的庫。雖然不一定會實現(xiàn)一個C++的語法分析器(實際上我可以告訴你我沒法產(chǎn)生精確的語法樹,如果不做語義分析我肯定不知道a<b,c>d;究竟是什么東西),但上下文無關(guān)著色什么的肯定是可以輕松實現(xiàn)的。】
編譯原理那些東西幾乎忘光……
我覺得為編輯器著色有一個相對于編譯器來說很麻煩的地方……
編譯器可以要求源代碼必須是合乎語法的,否則就報錯。
編輯器的著色分析就不能這么暴力了,它必須能夠接受半完整的源代碼,并且盡可能從中榨取出信息……
所以visual assistant還是很強大的……
【子類不需要非得實現(xiàn)什么,純粹是模擬非純虛函數(shù)。因為父類必須提供所有可以覆蓋的界面的空實現(xiàn),才可以讓實現(xiàn)控件的人,只寫他們關(guān)心的東西。】
上面已經(jīng)說明了:
"父類提供所有可以覆蓋的界面的空實現(xiàn)",或者說默認(rèn)實現(xiàn),并讓實現(xiàn)控件的人,只寫他們關(guān)心的東西 —— 這不需要ATL-style式的繼承,普通繼承就可以了。
只有在"向子類要求一些莫須有的東西"時,才需要依靠template。
【我重寫VL++的目的就是想提供一個用來分析字符串(速度不用爆快,但肯定要好用)的庫。雖然不一定會實現(xiàn)一個C++的語法分析器(實際上我可以告訴你我沒法產(chǎn)生精確的語法樹,如果不做語義分析我肯定不知道a<b,c>d;究竟是什么東西),但上下文無關(guān)著色什么的肯定是可以輕松實現(xiàn)的。】
編譯原理那些東西幾乎忘光……
我覺得為編輯器著色有一個相對于編譯器來說很麻煩的地方……
編譯器可以要求源代碼必須是合乎語法的,否則就報錯。
編輯器的著色分析就不能這么暴力了,它必須能夠接受半完整的源代碼,并且盡可能從中榨取出信息……
所以visual assistant還是很強大的……
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 21:08
@cexer
有點感覺了。
ATL-style繼承,一方面有點類類似concepts或者說ducking type的使用。
template<class D>
class B
{
void f()
{
D* d = static_cast<B*>(this);
d->must_have_this_function(); // 必須有某個成員函數(shù)
d->must_have_this_variable; // 必須有某個成員變量
typedef typename D::must_have_this_type type;
// 必須有某個嵌套類型
}
};
B可以對D提出一些要求,D必須滿足這些要求。
對這些要求,B可以不必提供"默認(rèn)實現(xiàn)"。
這2點就是和普通繼承很不相同的地方了。
同時,ATL并沒有通過"組合"來復(fù)用庫代碼,而是通過"共有實現(xiàn)繼承"來復(fù)用庫的代碼。
使得編寫的代碼會少一些。 就像那個著名的例子:
class person : public public nose, public mouth {};
person p;
p.eat(); mouth::eat
p.smell(); nose::smell
實際上呢,更"學(xué)術(shù)氣息"一些的方案是:
class person
{
nose n_;
mouth m_;
eye e_[2]; // left and right
public:
// forwarding functions
void eat() { m_.eat(); }
void smell() { n_.smell(); }
};
但是在界面開發(fā)中…… 這些轉(zhuǎn)發(fā)函數(shù)會寫死人的……
所以,就產(chǎn)生了ATL-style繼承 —— concepts(ducking type) + 實現(xiàn)繼承的結(jié)合。
只是為ATL-style繼承舉例的人的例子沒有選好,無法充分說明它的優(yōu)點。
我只粗看過《mfc程序員的wtl編程指南》還是什么的。
里面就是一個"沒有體現(xiàn)出base對derived的需求",可以用普通繼承改寫的例子。
這樣理解如何?
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 20:37
@cexer
【你試試不用虛函數(shù),不用ATL的這種編譯時的多態(tài)手法,在不知道子類為何物的情況下,在基類當(dāng)中調(diào)用子類的方法試試? 】
應(yīng)該是不行的。
只有template這種變態(tài)代碼生成器才可以:
template<typename T>
void f(T v)
{
v.f(); // 讓你先這么著了,等實例化的時候再做檢查……
}
如果不是模板,父類是不能調(diào)用子類函數(shù)的。
那么,ATL-style繼承的作用就是:實現(xiàn)靜態(tài)的"template method"?
【你試試不用虛函數(shù),不用ATL的這種編譯時的多態(tài)手法,在不知道子類為何物的情況下,在基類當(dāng)中調(diào)用子類的方法試試? 】
應(yīng)該是不行的。
只有template這種變態(tài)代碼生成器才可以:
template<typename T>
void f(T v)
{
v.f(); // 讓你先這么著了,等實例化的時候再做檢查……
}
如果不是模板,父類是不能調(diào)用子類函數(shù)的。
那么,ATL-style繼承的作用就是:實現(xiàn)靜態(tài)的"template method"?
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 20:29
@cexer
你說的是這種情況么?
non-template
class B
{
virtual void f_do() = 0;
void f()
{
... // 有一些其他工作,不僅僅是轉(zhuǎn)發(fā)
f_do();
...
}
};
B可以自己不實現(xiàn)f_do,并且具有這么一個限制:如果派生類不實現(xiàn)f_do,派生類將繼續(xù)無法實例化。
ATL-style繼承,提供"類似"的含義。
template<class D>
class B
{
void f()
{
... // 有一些其他工作,不僅僅是轉(zhuǎn)發(fā)
static_cast<D*>(this)->f_do();
...
}
};
class D : public B<D>
{
void f_do() { }
}
如果不實現(xiàn)f_do,D就會產(chǎn)生編譯錯誤。
類似于如果上面那種D如果不定義f_do就無法實例化。
普通繼承無法提供這種限制語意:
class B
{
void f()
{
... // 有一些其他工作,不僅僅是轉(zhuǎn)發(fā)
f_do();
...
}
// void f_do();
// 如果提供,派生類不不覆蓋也能實例化,也不會產(chǎn)生編譯錯誤。
// 無法達到限制"派生類必須提供"的目的
// 如果不提供,B就會產(chǎn)生鏈接錯誤。
};
是這樣嗎?
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 20:13
@陳梓瀚(vczh)
【header-only已經(jīng)不錯了,我現(xiàn)在最煩一個類要將界面重復(fù)在兩個文件里面。】
頭文件不行嗎?為什么會這樣?
【
話說我想嘗試自己實現(xiàn)BOOST_ITERATE(只用宏復(fù)制代碼)的方法,最后研究了好久,發(fā)現(xiàn)用C的宏是不對的,應(yīng)該自己制造代碼生成器……C的宏缺乏語法上的可維護性
】
我也覺得宏很不可靠……
有時候完全可以利用其他一些很方便的語言,來產(chǎn)生C/C++源代碼。
憑借C/C++自身機制來進行元編程,有時候會很…… 很麻煩……
比如boost.pp,它用來產(chǎn)生模板類型參數(shù)列表的這個功能,其實也可以寫一些其他語言的代碼,用來生成C++源代碼……
可讀性應(yīng)該會好很多……
【header-only已經(jīng)不錯了,我現(xiàn)在最煩一個類要將界面重復(fù)在兩個文件里面。】
頭文件不行嗎?為什么會這樣?
【
話說我想嘗試自己實現(xiàn)BOOST_ITERATE(只用宏復(fù)制代碼)的方法,最后研究了好久,發(fā)現(xiàn)用C的宏是不對的,應(yīng)該自己制造代碼生成器……C的宏缺乏語法上的可維護性
】
我也覺得宏很不可靠……
有時候完全可以利用其他一些很方便的語言,來產(chǎn)生C/C++源代碼。
憑借C/C++自身機制來進行元編程,有時候會很…… 很麻煩……
比如boost.pp,它用來產(chǎn)生模板類型參數(shù)列表的這個功能,其實也可以寫一些其他語言的代碼,用來生成C++源代碼……
可讀性應(yīng)該會好很多……
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 20:09
@陳梓瀚(vczh)
【其實我對語法最感興趣……因為我做編譯器……】
能否做一個,呃,怎么說呢……
visual assistant你肯定用的吧?類似的還有:
msvc,gcc :
synedit : http://synedit.sourceforge.net/
scintilla : http://www.scintilla.org/
還有一些C/C++源代碼轉(zhuǎn)換到html、pdf等格式的工具。
它們肯定都能分析C/C++源代碼。
但是源代碼分析后的結(jié)果,它們自產(chǎn)自銷了,沒有暴露出來。
你能否做做這方面的工作呢? 一個C/C++(或者其他語言)的源代碼分析器,將分析的結(jié)果暴露出來。
方便其他用途使用,比如代碼染色。
這樣,很多編輯器、網(wǎng)頁、甚至是pdf、doc都可以得益于你的工作。
而不是每個工具都自己實現(xiàn)一套(有的功能薄弱得……比如網(wǎng)頁上的染色,基本就只能認(rèn)識語言的關(guān)鍵字而已),然后自產(chǎn)自銷。
你覺得這個提議怎樣?
【其實我對語法最感興趣……因為我做編譯器……】
能否做一個,呃,怎么說呢……
visual assistant你肯定用的吧?類似的還有:
msvc,gcc :
synedit : http://synedit.sourceforge.net/
scintilla : http://www.scintilla.org/
還有一些C/C++源代碼轉(zhuǎn)換到html、pdf等格式的工具。
它們肯定都能分析C/C++源代碼。
但是源代碼分析后的結(jié)果,它們自產(chǎn)自銷了,沒有暴露出來。
你能否做做這方面的工作呢? 一個C/C++(或者其他語言)的源代碼分析器,將分析的結(jié)果暴露出來。
方便其他用途使用,比如代碼染色。
這樣,很多編輯器、網(wǎng)頁、甚至是pdf、doc都可以得益于你的工作。
而不是每個工具都自己實現(xiàn)一套(有的功能薄弱得……比如網(wǎng)頁上的染色,基本就只能認(rèn)識語言的關(guān)鍵字而已),然后自產(chǎn)自銷。
你覺得這個提議怎樣?
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 18:51
@陳梓瀚(vczh)
【
如何在屬性實現(xiàn)狀態(tài)變化控制的技術(shù)嘛,沒有說過命名……看來我們是互相誤解了啊……
】
那你也說說你的想法嘛……
比如那個“效率問題”應(yīng)該怎么理解?
有人說可以拿C/C++程序員作巴浦洛夫?qū)嶒灒刺岬?效率"2字時他們是否會流口水……
我沒有流口水…… 但是我很好奇……
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 18:39
@cexer
管飯的人呢……
這問題反復(fù)困擾我很久了…… 一直沒得到解答…… 于是塵封了……
用ATL/WTL的人很少,問都找不到人問……
今天終于找到管飯的了, 一定得追問到底~_~
管飯的人呢……
這問題反復(fù)困擾我很久了…… 一直沒得到解答…… 于是塵封了……
用ATL/WTL的人很少,問都找不到人問……
今天終于找到管飯的了, 一定得追問到底~_~
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 18:20
@陳梓瀚(vczh)
【如果你的庫不用dll+lib+h提供的話,請盡情使用模板】……
如果ATL-style繼承的好處就是為了header-only。
class Base
{
void OnDraw() { /* inline */ }
};
或者:
base.h
class Base
{
void OnDraw();
};
base.inl
#include "base.h"
inline void Base::OnDraw() {}
也可以是header-only ……
那么,ATL-style繼承,還有什么好處么……
一開始,我也覺得很神奇…… 后來越想越不是那么回事…… 然后一直沒想通……
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 18:16
@陳梓瀚(vczh)
@cexer
我上面也說了, 這和普通的繼承實現(xiàn)的功能是完全一樣的。
依然沒有虛函數(shù)開銷,依然有一點點"多態(tài)"。
用vczh的例子來說:
class Base
{
void OnDraw() { 空 }
};
class Derived1 : public Base
{
void OnDraw() { 我有新OnDraw }
};
class Derived2 : public Base
{
// 我用默認(rèn)Draw
};
不也一樣嗎? 除了Base現(xiàn)在是一個類,而不是類模板。
所以,我現(xiàn)在唯一想出的ATL-style繼承的優(yōu)勢就是:header-only。
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 18:06
@陳梓瀚(vczh)
【
屬性變化就是狀態(tài)變化嘛,你要監(jiān)聽一個狀態(tài)的變化,還要控制一個狀態(tài)變化的權(quán)限,用屬性+事件的組合是很常見的。也就是說,一個屬性都要自動提供Changing和Changed兩個事件。嘗試把它做得高效,就是我之前的需求了。
這才是屬性的本質(zhì)概念,跟語法什么的關(guān)系并不大。
】
我覺得你又開始繼續(xù)扯遠(yuǎn)了……
本來不是在討論“proxy的實現(xiàn)技術(shù)”“property和命名函數(shù)”么……
anyway,換個話題也好。
不過我真沒看明白你的需求是怎樣的……
這個需求是否高效,與“是否使用union”有關(guān)系嗎?
與“property vs 命名函數(shù)”有關(guān)系嗎?
是一個新話題吧?
能詳細(xì)說說你的需求么?
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 18:02
@cexer
ATL-style繼承,提供的語意是:
基類提供默認(rèn)實現(xiàn),派生類繼并覆蓋自己需要的函數(shù)。
是這樣嗎?
除了這個,還有其他功能嗎?
但這個功能,不正好就是非ATL-style繼承 —— 普通繼承提供的語意嗎……
為什么要繞這么大一個圈子?
能得到什么好處? header-only?
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 17:57
@cexer
【
絕沒問題,歡迎有自己思考的同志來此版聊,如果能切緊GUI框架的主題就感謝了哈,你們的討論能使我的博文增色不少。聊完不要走,此處管飯。
】
別管飯了…… 正好有一個懸了很久的關(guān)于ATL/WTL的疑問,你管管吧~_~
是這樣的,ATL/WTL中提到一種atl-style繼承。
template<typename D>
class B
{
void f1() { static_cast<D*>(this)->f1_do(); }
void f2() { static_cast<D*>(this)->f2_do(); }
void f1_do() { printf("B\n"); }
void f2_do() { printf("B\n"); }
};
class D : public B<D>
{
void f1_do() { printf("D\n"); }
};
D d;
d.f1();
D::f1不存在 -> 調(diào)用B::f1 -> 轉(zhuǎn)型為D* -> D覆蓋了f1_do -> 調(diào)用D::f1_do ->輸出"D"
d.f2();
D::f2不存在 -> 調(diào)用B::f1 -> 轉(zhuǎn)型為D* -> D::f2_do不存在 -> 調(diào)用B::f1_do->輸出"B"
是這樣嗎?
然后,問題就來了 …… 這個樣子,除了將代碼寫得更復(fù)雜以外,相比下面的寫法,有什么區(qū)別么??
class B
{
void f1() { printf("B\n"); }
void f2() { printf("B\n"); }
};
class D : public B
{
void f1() { printf("D\n"); }
};
D d;
d.f1(); "D"
d.f2(); "B"
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 17:43
【
1:先做的事情寫在前面,后做的事情寫在后面,要花時間看清楚。
2:不要造成括號的嵌套,難以維護。
舉個例子,挑選列表里面所有偶數(shù)的數(shù)字然后平方,如果你寫成square(even(a_list))就不滿足1和2。
【注意,上面兩點你看過就算了,我不討論好跟不好,因為跟主題沒關(guān)系】
】
不能算了……
text.onchange_set( handler1 ).onchange_add( handler2 ).onchange_add( handler3 );
滿足上面的2點嗎?
【
對于你的點的例子,我傾向于CalculateRadius(your_point)。你不能否認(rèn)人們總是下意識地認(rèn)為獲取屬性比調(diào)用函數(shù)的效率要高,所以那些真的做了事情,又不改變狀態(tài),又只讀的屬性變成函數(shù)比較好。
】
點的例子是因為你說point不需要行為而舉出的反例。
我也傾向于:
point
{
double x() const;
void x(double xx);
double r() const;
void r(double rr);
// ..
};
我也沒有假設(shè)get_r( p ); 和 p.r() 或者p.r到底何種效率更高。
這取決與內(nèi)部表達是直角坐標(biāo)還是極坐標(biāo)。
這些都不是重點。重點在于:
1. r絕對不可以是裸域 —— 它需要維護不變式
2. 如果你打算將x、y、r、a由函數(shù)變?yōu)閷傩裕?個指針的開銷你覺得是否合適?
btw:這4個屬性都可以是讀寫的,并不存在x、y讀寫,r、a只讀一說。
【
不過我還是想跟你討論“在一個包含請求回調(diào)doing和響應(yīng)回調(diào)one(+=也好,.Add也好)的屬性,怎么避免開銷”而不是在這里要不要用只讀的屬性。
】
我沒看明白,能否再詳細(xì)一點?
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 17:23
【我跟OwnWaterloo就借著你的地盤版聊了哈】
要不我們開一個論壇吧?google groups或者群?
群的聊天資料可能不容易搜出來……
toplangauge越來越水了……
把cppblog上的人都招集起來?
很高興和你們討論問題~_~
如果我語氣有過激之處,請不吝指出,或者多多包涵一下。
有人響應(yīng)沒……?
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 17:19
【我并沒有反對你優(yōu)化,我只是說“你覺得在一個【上百個】屬性的Form里面,你打算怎么處理屬性和事件之間的關(guān)系”。正好本篇是談GUI,因此舉這么個例子我覺得挺合適的。那我就這么問吧,我以為你是知道我在說什么的:在一個包含請求回調(diào)doing和響應(yīng)回調(diào)one(+=也好,.Add也好)的屬性,怎么避免開銷?】
首先,上百個屬性是否可以改為上百個×2的getter和setter?
setter不一定難用,setter還可以鏈?zhǔn)奖磉_呢。
對比:
1. w.p1(v1).p2(v2).p3(v3) ...
2. ( (w.p1 = v1).p2 = v2 ).p3 = v3 ...
3.
w.p1 = v1;
w.p2 = v2;
w.p3 = v3;
其次,如果真要模擬property。
我真的沒看明白你說的那個需求是什么…… 囧
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 17:11
【行為指的是受改變的時候發(fā)生的事情,而不是你能從一個數(shù)據(jù)里面計算出什么東西。坐標(biāo)轉(zhuǎn)換是映射,點在任何情況下都不可能因為你設(shè)置了一個什么坐標(biāo)而做了一些什么事情,因此沒有行為。當(dāng)然cache不同坐標(biāo)系下的結(jié)果例外,這不是重點。】
可能我們對“行為”這個詞有不同的理解。 那我們不用這個詞了。
對剛才說的點的例子。半徑絕對不能直接讀寫對吧?
所以必須將實現(xiàn)隱藏起來(實現(xiàn)可能是以直角坐標(biāo)存儲), 通過setter/getter去操作,以維護點的不變式 —— 半徑不可能小于0。
我說的就是這個意思。
如果你需要可按極坐標(biāo)操作的點,就不能直接暴露數(shù)據(jù),必須使用setter/getter或者property。
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 17:06
【【窄化】不是問題。GUI是一個龐大的東西,一旦需要了,那就有做的必要,就算除了GUI以外的所有系統(tǒng)都不能從這個property機制上獲得好處,也不是不搞的理由。而且讓一個例子舉現(xiàn)在一個范圍里面可以讓我們都少想很多東西。】
就算這種O(n)到O(1)的優(yōu)化因為它太復(fù)雜而永遠(yuǎn)用不上,【也不是不搞的理由】。
我這么說對嗎?
討論如何優(yōu)化就是討論如何優(yōu)化。
沒有必要將這種討論限制到某個范圍內(nèi),然后說在這個范圍內(nèi)不需要這種優(yōu)化。
你不能預(yù)見所有場合都不需要這種優(yōu)化。
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 17:01
【至于其他的例子,你可以參考WPF強大的布局功能是怎么【under control】的,用傳統(tǒng)的方法根本沒法讓程序變得清晰。】
我不懂wpf。
不通過屬性,而是命名方法,可以做到讓程序清晰么?
如果只是從:
textBox.Text.OnChanging+=a_functor_that_want_to_check_the_input;
變化到:
textBox.Text.OnChanging.add( a_functor_that_want_to_check_the_input );
textBox.Text.OnChangingSet( a_functor_that_want_to_check_the_input );
textBox.Text.OnChangingAdd( a_functor_that_want_to_check_the_input );
我覺得依然很清晰。
也許前者對C#轉(zhuǎn)到C++的程序員來說,前者會很親切。
但后者才是大部分C++程序員的每天都在使用形式。
你不需要給你的用戶培訓(xùn)“C++中如何模擬property”這種細(xì)節(jié),他就可以使用你的api。
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 16:56
【其實舉過了嘛,textBox.Text.OnChanging+=a_functor_that_want_to_check_the_input;你覺得在一個【上百個】屬性的Form(你不要告訴我一個窗口的狀態(tài)很少)里面,你打算怎么處理屬性和事件之間的關(guān)系,我一直都在強調(diào)這一點,而不是語法上的問題,operator=其實也是個例子,我沒有強調(diào)說要不要有個名字之類的東西。 】
textBox.Text.OnChanging+=a_functor_that_want_to_check_the_input;
你覺得改成這樣,可接受不?
textBox.Text.OnChanging.add( a_functor_that_want_to_check_the_input );
textBox.Text.OnChangingSet( a_functor_that_want_to_check_the_input );
textBox.Text.OnChangingAdd( a_functor_that_want_to_check_the_input );
C++就是C++,沒有必要模擬.net那一套。
【另外,不要覺得什么掉價不掉價的,技術(shù)沒有貴賤之分,不要搞三六九等。話說我自己在搞語言設(shè)計和實現(xiàn)。從來跟這些property什么的關(guān)系不大,這估計是職業(yè)病。】
因為我覺得通過union來達到property的額外空間與property數(shù)量無關(guān)這個技巧可能是新奇的。我沒有在其他地方看到過,也是我自己想出來的。
而proxy的那些技巧,我已經(jīng)看太多,說不定大家都知道,我又何必多次一舉?
而且很多都不是我獨立想出來的。
所以我覺得說出來很掉價……
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 16:42
"當(dāng)然這要看情況了。在我看來,每一個控件都要實現(xiàn)可監(jiān)聽的屬性,這些屬性用事件暴露出來。你愿意設(shè)計完屬性之后從頭設(shè)計一次事件的命名和參數(shù)什么的好,還是愿意把它們綁定到屬性里面去?這樣的話開發(fā)控件也不需要考慮提供的事件完整不完整的問題了。因為控件的狀態(tài)都在屬性里面,屬性變更就是狀態(tài)變更,也就都有事件了。這樣做的話設(shè)計出來的控件就不會有winapi那個消息(我們都知道很難清洗化)的影子了,會有一個十分漂亮的設(shè)計出來。"
消除winapi的影子,一定需要屬性嗎?命名函數(shù)不可以嗎?
如果語言本身提供屬性,那使用兩者之一都沒什么問題。
如果語言本身不提供,為何在可以使用命名函數(shù)的地方,非要去使用屬性???
"一般winapi封裝出來的東西都是在PC上跑的,你會在意一個textbox占了1k還是1.1k內(nèi)存嗎?在這里多一個指針少一個指針根本不是問題。 "
在gui上,你的說法是正確的。你甚至可以使用boost::any + boost::tuple來得到一個類似python的開發(fā)方式。
我討論的是"proxy得到object", 請不要將討論窄化gui上。
作為一個庫(非gui庫)的提供者,效率不是最主要的,但無端的損害(大量損害)就是不可接受的了。
假設(shè)某天你真的需要將proxy應(yīng)用到critical的場景,你就會后悔當(dāng)初沒有去考慮這個問題了。
"特別是對于point,那就是個變量好了,point沒有行為,所以不需要屬性。"
需要的。我舉個例子:
point
{
property double x { get;set; }
property double y { get;set; }
property double radius { get; set; }
property double seta { get; set; }
};
客戶可以用直角坐標(biāo)或者極坐標(biāo)去操作這個點。
點的內(nèi)部表示客戶無須關(guān)心。
這樣的點,就需要行為。
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 16:32
"模擬屬性一點都不無聊,因為一個可以監(jiān)聽和撤銷屬性變化的系統(tǒng)非常容易擴展,總比你一個類都來一個listener或者就像api一樣所有的消息的格式都很混亂的好。特別對于開發(fā)GUI的庫。當(dāng)然這就不僅僅是如何響應(yīng)operator=的問題了。允許阻止變化的listener總是有開銷的,所以你無法杜絕它。這也是我第一次舉例子的時候就說出來的一個可以認(rèn)為是“需求”的東西。"
模擬屬性就是很無聊的工作。
你試著回答一個問題:”這里一定需要operator=嗎? 可以使用命名函數(shù)嗎?
如果回答是“是” ,那這里就寧可采用命名函數(shù),而不是屬性。
絕大部分回答都應(yīng)該是“是”。所以這根本不算一個需求。
從我的直覺上來說,模擬屬性使用的價值并不大。沒有多少場合非屬性不可。
如果你可以想到一個“不是”的例子,請列舉出來。
也許我的直覺是錯的。
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 16:32
"模擬屬性一點都不無聊,因為一個可以監(jiān)聽和撤銷屬性變化的系統(tǒng)非常容易擴展,總比你一個類都來一個listener或者就像api一樣所有的消息的格式都很混亂的好。特別對于開發(fā)GUI的庫。當(dāng)然這就不僅僅是如何響應(yīng)operator=的問題了。允許阻止變化的listener總是有開銷的,所以你無法杜絕它。這也是我第一次舉例子的時候就說出來的一個可以認(rèn)為是“需求”的東西。"
模擬屬性就是很無聊的工作。
你試著回答一個問題:”這里一定需要operator=嗎? 可以使用命名函數(shù)嗎?
如果回答是“是” ,那這里就寧可采用命名函數(shù),而不是屬性。
絕大部分回答都應(yīng)該是“是”。所以這根本不算一個需求。
從我的直覺上來說,模擬屬性使用的價值并不大。沒有多少場合非屬性不可。
如果你可以想到一個“不是”的例子,請列舉出來。
也許我的直覺是錯的。
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 16:27
"舉個簡單的例子,總線形式的開發(fā)會讓string有一個c_str(),而不是讓string消失。我不知道你知不知道解決方案是什么樣子的,但是舉個例子出來總是要告訴別人說,“哦,這個東西可以這么這么做,只是我懶的寫完整”而不是沒說完。"
我相信看的人能明白我代碼中的重點在那里。
我不明白的是你為何看不明白,即使在我說了之后。
我再說一下吧,如果要讓我說"這個property"還可以這樣玩、又可以那樣玩,我會覺得很掉價……
一方面因為我現(xiàn)在本來就不喜歡過分玩弄語言特性。
另一方面,這些技術(shù)實在是說得太多……
如果一定要把所有細(xì)節(jié)都展現(xiàn)出來,不知道評論的字?jǐn)?shù)會不會夠。
而且,展現(xiàn)到什么程度才可以停止?
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 16:15
@陳梓瀚(vczh)
"在關(guān)心程序的質(zhì)量的同時,也要同時關(guān)心一下如何將廣大程序猿在C++的水深火熱之中解放出來"
我展示的,只是"proxy得到object"的技術(shù)。
你可以繼續(xù)展示proxy得到object之后的"解救廣大C++程序員于水深火熱之中"的其他技術(shù)。
但說實話,我不覺得那些技術(shù)真的能救人于水火。
真正救人于水火的,不是玩弄高級技巧,而是設(shè)計清晰的接口。
還是上面的例子:
C c;
C2 c2;
c.f( c2.i ); 不能這樣做,只會讓人感到困擾。
如果i不是屬性,而是成員:
c.f( c2.i() ); 不行是很容易理解事情 —— 臨時對象不能綁定到非const引用上。
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 16:07
@陳梓瀚(vczh)
"不過用了union,而跟你剛才那樣一個屬性就要定義一個類,而不是一種類型的屬性定義一個類(或者干脆就只有少數(shù)幾個屬性的類然后到處使用——這個要求比較高了一點),我覺得比多一個指針更加不能接受。運行時代價跟開發(fā)代價都是需要一并考慮的。"
先說運行代價和開發(fā)代價。
C程序員可能會因為效率,不使用qsort。 他們都是傻子嗎?
"實現(xiàn)屬性占用的額外空間大小與屬性的數(shù)量無關(guān)",這難道真的不值得你為其多花點功夫嗎?
這是O(n)到O(1)的優(yōu)化!是不值得的?!
而且我比較懷疑你所說的"一種類型的屬性定義一個類"是一種[color=red]侵入式[/color]的實現(xiàn)方式。
需要實現(xiàn)屬性的類本來就不應(yīng)該很多。
我也想如何做得更范化一些, 但目前成效不大。
就像cexer說的"高效的,不會制造麻煩的東西,也是從不高效的,會制造麻煩的東西進化來的。"
如果一開始就采用指針保存,那是一輩子就沒辦法優(yōu)化了。
"不過用了union,而跟你剛才那樣一個屬性就要定義一個類,而不是一種類型的屬性定義一個類(或者干脆就只有少數(shù)幾個屬性的類然后到處使用——這個要求比較高了一點),我覺得比多一個指針更加不能接受。運行時代價跟開發(fā)代價都是需要一并考慮的。"
先說運行代價和開發(fā)代價。
C程序員可能會因為效率,不使用qsort。 他們都是傻子嗎?
"實現(xiàn)屬性占用的額外空間大小與屬性的數(shù)量無關(guān)",這難道真的不值得你為其多花點功夫嗎?
這是O(n)到O(1)的優(yōu)化!是不值得的?!
而且我比較懷疑你所說的"一種類型的屬性定義一個類"是一種[color=red]侵入式[/color]的實現(xiàn)方式。
需要實現(xiàn)屬性的類本來就不應(yīng)該很多。
我也想如何做得更范化一些, 但目前成效不大。
就像cexer說的"高效的,不會制造麻煩的東西,也是從不高效的,會制造麻煩的東西進化來的。"
如果一開始就采用指針保存,那是一輩子就沒辦法優(yōu)化了。
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 15:59
@陳梓瀚(vczh)
"如果別人解決了一個帶多余指針的好用的屬性,你解決了一個不帶多余指針的不好用的屬性,那都是沒意義的。"
我那個是沒有意義的?
我那個不可以繼續(xù)實現(xiàn)你所說的那些花哨的用法嗎?(為什么說花哨,我下面會說明)
我已經(jīng)說過很多次了,"通過proxy得到被proxy的對象"是實現(xiàn)proxy的前提。
必須先滿足這個前提才能繼續(xù)實現(xiàn)proxy的其他技巧。
用union會影響實現(xiàn)其他技巧嗎? 依然可以。
難道我要把所有我會的技巧都展現(xiàn)一下嗎?
我不喜歡這樣[color=red]顯擺[/color]。
或者說,我也喜歡顯擺;但[b]我不喜歡顯擺[color=red]眾人皆會[/color]的技巧[/b]。
分享一些別人明顯了解的技術(shù),只會[b][color=red]漲[/color]別人眼睛[/b]。
我只想展示如何高效實現(xiàn)proxy所需前提這一技巧,如是而已。
btw:為什么我說你那些是花哨的技巧。
首先引入一個概念:"總線式的設(shè)計"。
假設(shè)你需要實現(xiàn)一個函數(shù)f,f需要一個字符串輸入(暫不考慮wchar_t)。
如何設(shè)計這個輸入?yún)?shù)???
1. f(const char* c_style_string);
2. f(const char* first,ptrdiff_t length);
兩者取其一,可能1用得更多一些。
然后,其他所有的String,都向這個"總線" —— const char*靠攏。
比如std::basic_string要提供c_str(), CString要提供operator const char*()。
為什么要這么做?
1. 避免API的暴增。 直連線是平方增長,而總線是線性增長。
2. 有些時候,必須這樣
對fopen(const char*)你可以繼續(xù)直連線:
fopen(const std::string& );
fopen(const CString& );
對一個類:
class C {
open(const char* );
};
C不是你寫的,你不可能為C加入一個直連線。
你只能繞彎:
open( C& o, const std::string& );
open( C& o, const CStirng& );
回到你說的ref<T>。
假設(shè)有一個函數(shù):
f(int& );
你可以為它直連線。
假設(shè)有一個類,依然不是你寫的,它只接受int &
class C
{
f(int & );
}
C2有一個屬性i。
class C2
{
property int i;
}
你要怎么給你的用戶解釋:
C c;
C2 c2;
c.f( c2.i ); 是行不通的,必須
f( c, c2.i ); ???
你能將所有api的匯合點都直連線嗎? 你做不到。
本來模擬屬性就是一個很無聊的事情了。
你告訴用戶,這就是一個C#中的 get; set; 就ok了,別想著要其他怎么用。
C#中可以 &o.p嗎???
"運行時代價跟開發(fā)代價都是需要一并考慮的。"
你看你是否自相矛盾了。
將線性開發(fā)代價的總線形式,轉(zhuǎn)化為平方開發(fā)代價的直連線形式。
"如果別人解決了一個帶多余指針的好用的屬性,你解決了一個不帶多余指針的不好用的屬性,那都是沒意義的。"
我那個是沒有意義的?
我那個不可以繼續(xù)實現(xiàn)你所說的那些花哨的用法嗎?(為什么說花哨,我下面會說明)
我已經(jīng)說過很多次了,"通過proxy得到被proxy的對象"是實現(xiàn)proxy的前提。
必須先滿足這個前提才能繼續(xù)實現(xiàn)proxy的其他技巧。
用union會影響實現(xiàn)其他技巧嗎? 依然可以。
難道我要把所有我會的技巧都展現(xiàn)一下嗎?
我不喜歡這樣[color=red]顯擺[/color]。
或者說,我也喜歡顯擺;但[b]我不喜歡顯擺[color=red]眾人皆會[/color]的技巧[/b]。
分享一些別人明顯了解的技術(shù),只會[b][color=red]漲[/color]別人眼睛[/b]。
我只想展示如何高效實現(xiàn)proxy所需前提這一技巧,如是而已。
btw:為什么我說你那些是花哨的技巧。
首先引入一個概念:"總線式的設(shè)計"。
假設(shè)你需要實現(xiàn)一個函數(shù)f,f需要一個字符串輸入(暫不考慮wchar_t)。
如何設(shè)計這個輸入?yún)?shù)???
1. f(const char* c_style_string);
2. f(const char* first,ptrdiff_t length);
兩者取其一,可能1用得更多一些。
然后,其他所有的String,都向這個"總線" —— const char*靠攏。
比如std::basic_string要提供c_str(), CString要提供operator const char*()。
為什么要這么做?
1. 避免API的暴增。 直連線是平方增長,而總線是線性增長。
2. 有些時候,必須這樣
對fopen(const char*)你可以繼續(xù)直連線:
fopen(const std::string& );
fopen(const CString& );
對一個類:
class C {
open(const char* );
};
C不是你寫的,你不可能為C加入一個直連線。
你只能繞彎:
open( C& o, const std::string& );
open( C& o, const CStirng& );
回到你說的ref<T>。
假設(shè)有一個函數(shù):
f(int& );
你可以為它直連線。
假設(shè)有一個類,依然不是你寫的,它只接受int &
class C
{
f(int & );
}
C2有一個屬性i。
class C2
{
property int i;
}
你要怎么給你的用戶解釋:
C c;
C2 c2;
c.f( c2.i ); 是行不通的,必須
f( c, c2.i ); ???
你能將所有api的匯合點都直連線嗎? 你做不到。
本來模擬屬性就是一個很無聊的事情了。
你告訴用戶,這就是一個C#中的 get; set; 就ok了,別想著要其他怎么用。
C#中可以 &o.p嗎???
"運行時代價跟開發(fā)代價都是需要一并考慮的。"
你看你是否自相矛盾了。
將線性開發(fā)代價的總線形式,轉(zhuǎn)化為平方開發(fā)代價的直連線形式。
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 14:02
@cexer
我再想想如何做得更范化一些。
減少需要編寫property的人的重復(fù)勞動。
但是遇到了困難……
手工寫union base, union member沒什么問題。
要將其做成模板…… 會遇到先有雞還是先有蛋的問題……
比如:
proxy< ..., getter , ... >
實例化一個property:
proxy< ..., &date::get_second, ... >; 這里需要date的定義?
而date的定義無論是union base,union member又需要先實例化proxy< ... &date::get_second, ... >;……
很囧……
手工寫沒問題是因為:
struct second_proxy {
這里僅僅聲明其布局就可以了
};
然后定義date類
然后實現(xiàn)proxy::op ...
這里才需要引用到date::&getter
我再想想……
我再想想如何做得更范化一些。
減少需要編寫property的人的重復(fù)勞動。
但是遇到了困難……
手工寫union base, union member沒什么問題。
要將其做成模板…… 會遇到先有雞還是先有蛋的問題……
比如:
proxy< ..., getter , ... >
實例化一個property:
proxy< ..., &date::get_second, ... >; 這里需要date的定義?
而date的定義無論是union base,union member又需要先實例化proxy< ... &date::get_second, ... >;……
很囧……
手工寫沒問題是因為:
struct second_proxy {
這里僅僅聲明其布局就可以了
};
然后定義date類
然后實現(xiàn)proxy::op ...
這里才需要引用到date::&getter
我再想想……
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 13:50
@陳梓瀚(vczh)
1.
如果一個property需要消耗一個指針的代價,我認(rèn)為實現(xiàn)得再好用都是不可接受的…… 高得有點離譜。
很容易一個類的property的消耗比類本身還要高。
[data of instance]
[pointer]
[pointer]
[pointer]
[pointer]
....
而且所有pointer都指向同一個地方……
而且上面也提到,真正需要模擬出property的,是類似于point、vector、matrix這種類。
p.x比p.x()更自然。
讓這種類附加額外數(shù)據(jù),也是讓人很難接受的。
2.
是否好用,你可以另外開文章討論。
只是你提到的那些使得proxy好用的技術(shù),都提不起我的興趣。
理由很簡單 —— 這種文章太多,寫出來都不好意思和人打招呼。
我關(guān)心的僅僅是proxy如何高效得到被proxy對象 —— 實現(xiàn)proxy的前提。
我以前見過的,包括我自己想到的,都是上面one property one pointer的方案。imp cpp中提到的讓我確實有眼前一亮的感覺。
而 op T(), op= (T), ref T op + 這些技術(shù),只讓我覺得漲眼睛 —— 看太多,早膩歪了。
如果你的重點依然在proxy如何更仿真上,可能很難提起我的興趣。
如果你有興趣思考proxy如何得到被proxy的object上,或者有一些方案,想法,歡迎分享出來~_~
"當(dāng)且僅當(dāng)好用,才有繼續(xù)考慮有沒有消耗的必要。一個高效的、會制造麻煩的解決方案一般是不被接受的。"
這句話絕對說得過于絕對了。
如果你用的是C++、而不是C#,效率絕對不是可以不掛在心上的事情。
為什么你要用C++,而不是用編程更方便,語法糖更多的C#?好好想想吧。
1.
如果一個property需要消耗一個指針的代價,我認(rèn)為實現(xiàn)得再好用都是不可接受的…… 高得有點離譜。
很容易一個類的property的消耗比類本身還要高。
[data of instance]
[pointer]
[pointer]
[pointer]
[pointer]
....
而且所有pointer都指向同一個地方……
而且上面也提到,真正需要模擬出property的,是類似于point、vector、matrix這種類。
p.x比p.x()更自然。
讓這種類附加額外數(shù)據(jù),也是讓人很難接受的。
2.
是否好用,你可以另外開文章討論。
只是你提到的那些使得proxy好用的技術(shù),都提不起我的興趣。
理由很簡單 —— 這種文章太多,寫出來都不好意思和人打招呼。
我關(guān)心的僅僅是proxy如何高效得到被proxy對象 —— 實現(xiàn)proxy的前提。
我以前見過的,包括我自己想到的,都是上面one property one pointer的方案。imp cpp中提到的讓我確實有眼前一亮的感覺。
而 op T(), op= (T), ref T op + 這些技術(shù),只讓我覺得漲眼睛 —— 看太多,早膩歪了。
如果你的重點依然在proxy如何更仿真上,可能很難提起我的興趣。
如果你有興趣思考proxy如何得到被proxy的object上,或者有一些方案,想法,歡迎分享出來~_~
"當(dāng)且僅當(dāng)好用,才有繼續(xù)考慮有沒有消耗的必要。一個高效的、會制造麻煩的解決方案一般是不被接受的。"
這句話絕對說得過于絕對了。
如果你用的是C++、而不是C#,效率絕對不是可以不掛在心上的事情。
為什么你要用C++,而不是用編程更方便,語法糖更多的C#?好好想想吧。
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 13:19
@陳梓瀚(vczh)
還是用代碼說話吧……
上面的date的代碼,重點在于這2行:
union { /* ... */ };
哦,還有一行在我的測試代碼中,并沒有抄出來:
typedef int assume[sizeof(date)==sizeof(time_t)?1:-1];
這2行才是我想表達的重點 —— 沒有額外的空間消耗,實現(xiàn)property。
寫上面那些代碼,為的是展示上面那個重點,而不是下面這種爛大街的:
operator = (int);
operator int() const;
這些技術(shù)早就被人討論得七七八八了,相當(dāng)無聊……
這一點不知道你看出來了沒?
還是用代碼說話吧……
上面的date的代碼,重點在于這2行:
union { /* ... */ };
哦,還有一行在我的測試代碼中,并沒有抄出來:
typedef int assume[sizeof(date)==sizeof(time_t)?1:-1];
這2行才是我想表達的重點 —— 沒有額外的空間消耗,實現(xiàn)property。
寫上面那些代碼,為的是展示上面那個重點,而不是下面這種爛大街的:
operator = (int);
operator int() const;
這些技術(shù)早就被人討論得七七八八了,相當(dāng)無聊……
這一點不知道你看出來了沒?
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 13:12
@陳梓瀚(vczh)
我在上面的評論也說了,在C++中沒有絕對必要,還是不要模擬這個東西了。
沒有property,生活一樣可以繼續(xù)。
至于 o.p1 + p.p2, &p.p1, 等模擬,并不是重點。
proxy本來就和被proxy的對象有所區(qū)別。
視你需要模擬的程度來決定編程的復(fù)雜度,或者發(fā)現(xiàn)某種特性無法實現(xiàn)。
proxy的重點在于如何高效的在proxy中得到被proxy對象。
實現(xiàn)了這個功能點,才是其他op=,op T(), op +, ref proxy的前提 —— 這些技術(shù)基本屬于濫大街了 —— 去看vector<bool> —— 所以我對這些沒什么興趣。
之所以重新開始研究這個技巧,是因為Imperfect C++中提到了一種代價很低的方案。
我覺得這個有點意思,所以繼續(xù)深入了一下。
我在上面的評論也說了,在C++中沒有絕對必要,還是不要模擬這個東西了。
沒有property,生活一樣可以繼續(xù)。
至于 o.p1 + p.p2, &p.p1, 等模擬,并不是重點。
proxy本來就和被proxy的對象有所區(qū)別。
視你需要模擬的程度來決定編程的復(fù)雜度,或者發(fā)現(xiàn)某種特性無法實現(xiàn)。
proxy的重點在于如何高效的在proxy中得到被proxy對象。
實現(xiàn)了這個功能點,才是其他op=,op T(), op +, ref proxy的前提 —— 這些技術(shù)基本屬于濫大街了 —— 去看vector<bool> —— 所以我對這些沒什么興趣。
之所以重新開始研究這個技巧,是因為Imperfect C++中提到了一種代價很低的方案。
我覺得這個有點意思,所以繼續(xù)深入了一下。
re: SFINEA in C++ OwnWaterloo 2009-11-16 03:58
@唐風(fēng)
我試試 …… 謝謝~_~
我試試 …… 謝謝~_~
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-16 02:48
關(guān)于隱藏time_成員……
1.
class C
{
public:
union
{
proxy1 property1;
proxy2 property2;
proxy3 property3;
// private: // msvc和gcc這里是不能加入private的(具體要查標(biāo)準(zhǔn))
}
};
{
public:
union
{
proxy1 property1;
proxy2 property2;
proxy3 property3;
// private: // msvc和gcc這里是不能加入private的(具體要查標(biāo)準(zhǔn))
}
};
2.
class C
{
public:
union
{
proxy1 property1;
proxy2 property2;
proxy3 property3;
}
private:
struct impl impl_; // 一旦不放在union中
// properties就可能會被填充
{
public:
union
{
proxy1 property1;
proxy2 property2;
proxy3 property3;
}
private:
struct impl impl_; // 一旦不放在union中
// properties就可能會被填充
};
仔細(xì)選擇union的位置,可能會起到減少總大小的效果,比如:
class C1 {
char c_;
public:
union { /* properties */ };
private:
int i_;
};
class C2 {
int i_;
char c_;
public:
union { /* properties */ };
};
因為char c_;的附近本來就會被填充,properties剛好占據(jù)那個位置。
如果這樣,就可能會很糟糕:
class C3 {
char c_;
int i_;
public:
union { /* properties */ };
};
C++標(biāo)準(zhǔn)沒有說class的layout應(yīng)該怎么安排。
每個access secion中的data,必須按聲明順序。
但不同access secion之間,可以打亂順序 —— 這個也許會有一些幫助。
第2種方案依然需要計算offsetof…… 這是很不靠譜的……
3.
作為base。
struct properties
{
union
{
proxy1 property1;
proxy2 property2;
proxy3 property3;
proxy2 property2;
proxy3 property3;
// ...
}
};
class C : public properties
{
// data
};
這樣,可以很容易計算出C的位置:
void property_proxy::operator=( ... ) {
void* p = this;
C* c = static_cast<C*>( static_cast<properties*>(p) );
}
編譯器會正確計算出C*,即使在多繼承下也行。比如:
class C : other , public properties {};
但是,在msvc和gcc上,properties 都不會執(zhí)行空基類優(yōu)化…… 很囧……
仔細(xì)安排data的布局(在這2款編譯器上,將小對齊的數(shù)據(jù)放前面),也會影響整個類的大小。
2和3的方案,如果能鉆到空子,就可以幾乎沒有代價的實現(xiàn)property。
空子就是說,那個class本來就有一些需要被填充的空洞……
如果沒有空可鉆…… 或者沒有正確安排位置…… 會多占用一些大小。
額外大小不超過class中所有域中需要最大對齊那個成員的大小。
額外大小和properties的數(shù)量是無關(guān)的, 多少個properties都占用這么多額外大小, union嘛……
4.
還有一種方案。
其實上面的date,缺陷在于time_t time_; 這個成員會被外界訪問。
可以這樣:
class date {
class impl {
time_t time_;
friend class date;
};
public:
union
{
impl impl_;
proxy1 property1;
proxy2 property2;
proxy3 property3;
proxy2 property2;
proxy3 property3;
}
// ...
};
這樣,客戶代碼可以訪問的,只有impl_這個名字。
但是幾乎不能拿它作任何事情。
連它的類型名 —— date::impl —— 都是不可訪問的。
這個方案的缺陷就是 —— 通常必須從頭設(shè)計一個類型。
union中不能放非pod。只能從內(nèi)建類型開始,構(gòu)造一些類。
比如已經(jīng)有某個非pod的類,C,想將C作為一個成員,實現(xiàn)Cex:
class Cex
{
union
{
C impl_; // 不行
}
};
只能用上面的property base或者property member……
5.
范化工作
這個…… 再說吧……
如果能有更好的布局方案…… 范化工作就白做了……
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-15 22:33
@cexer
關(guān)鍵點在于:"如何通過proxy地址,得到object地址"。
1. 可以給proxy放入一個object的指針。每個proxy消耗一個指針的空間。
太浪費了……
2. Imperfect C++中利用offset來計算object的地址,使得每個proxy不含任何域。
但C++為了區(qū)別各個proxy,會給每個proxy進行填充,依然會造成消耗。
但C++為了區(qū)別各個proxy,會給每個proxy進行填充,依然會造成消耗。
3. 避免proxy在Record中被填充
假設(shè)有如下記錄:
Record
{
proxy1 property1;
proxy2 property2;
proxy3 property3;
Record
{
proxy1 property1;
proxy2 property2;
proxy3 property3;
...
}
}
其中proxy1,proxy2,proxy3, ... 是空結(jié)構(gòu)。
Record r;
r.property1;
r.property2;
r.property3;
r.property1;
r.property2;
r.property3;
...
在C/C++中,如果想要property1、2、3、... 不占空間,也就是它們必須擁有相同的地址。
也就是說…… Record 是union……
4. 避免Record在class中被填充
即使這樣,整個union依然是會被填充……
所以,可以將class的數(shù)據(jù)和union放在一起,就真的不消耗任何空間了……
(如果類本身不需要數(shù)據(jù),那這個類也是會被填充的,proxys依然沒有消耗多余的空間)
所以,可以將class的數(shù)據(jù)和union放在一起,就真的不消耗任何空間了……
(如果類本身不需要數(shù)據(jù),那這個類也是會被填充的,proxys依然沒有消耗多余的空間)
代碼:
class date
{
private:
struct second_proxy
{
operator int() const
{
const void* o = this;
int sec = static_cast<const date*>(o)->get_second();
printf("%d second_proxy::operator int(%p);\n",sec,o);
return sec;
}
date& operator=(int sec)
{
void* o = this;
printf("second_proxy::operator=(%p,%d);\n",o,sec);
date* d = static_cast<date*>(o);
d->set_second(sec);
return *d;
}
};
public:
union
{
time_t time_;
second_proxy second;
};
date()
{
printf("date::date(%p);\n",(void*)this);
time(&time_);
}
int get_second() const
{
int sec = localtime(&time_)->tm_sec;
printf("%d date::get_second(%p);\n",sec,(void*)this);
return sec;
}
void set_second(int sec)
{
printf("date::set_second(%p,%d);\n",(void*)this,sec);
tm t = *localtime(&time_);
t.tm_sec = sec;
time_ = mktime(&t);
}
};
{
private:
struct second_proxy
{
operator int() const
{
const void* o = this;
int sec = static_cast<const date*>(o)->get_second();
printf("%d second_proxy::operator int(%p);\n",sec,o);
return sec;
}
date& operator=(int sec)
{
void* o = this;
printf("second_proxy::operator=(%p,%d);\n",o,sec);
date* d = static_cast<date*>(o);
d->set_second(sec);
return *d;
}
};
public:
union
{
time_t time_;
second_proxy second;
};
date()
{
printf("date::date(%p);\n",(void*)this);
time(&time_);
}
int get_second() const
{
int sec = localtime(&time_)->tm_sec;
printf("%d date::get_second(%p);\n",sec,(void*)this);
return sec;
}
void set_second(int sec)
{
printf("date::set_second(%p,%d);\n",(void*)this,sec);
tm t = *localtime(&time_);
t.tm_sec = sec;
time_ = mktime(&t);
}
};
second_proxy hour和date的數(shù)據(jù)time_t time_放在同一個union中。
這樣,它們擁有相同的地址。
在second_proxy::operator int() const; 中,可以直接將this轉(zhuǎn)換到const date* ……
就這樣得到了…… object的地址……
在C中,必須給那個union取一個名字:
struct date
{
union
{
time_t time_;
second_proxy second;
} must_have_a_name;
};
struct date date;
date.must_have_a_name.second; 必須這樣訪問……
C++中有匿名聯(lián)合,所以可以直接:
date d;
d.second;
這樣的壞處也很明顯……
客戶代碼可以訪問 d.time_; 什么都完蛋了……
我再想想怎么隱藏……
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-15 22:02
@cexer
我想到一個幾乎沒有消耗的方案……
我再完善一下……
我想到一個幾乎沒有消耗的方案……
我再完善一下……
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-15 20:31
@cexer
Imperfect C++中的差不多看明白了……
proxy是包含在object中,通過proxy在object中的offset得到object的地址……
Imperfect C++中的差不多看明白了……
proxy是包含在object中,通過proxy在object中的offset得到object的地址……
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-15 19:57
我暈……
侵入式的property……
強大……
侵入式的property……
強大……
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-15 19:43
我去看了看Imperfect C++。因為是英文的,以前只看了一部分就停了……
我覺得前面都寫得不錯,ABI、mangling這些問題確實是很困擾……
但property…… 我覺得這并不算C++的Imperfection。
完全是被其他語言給蒙蔽了。
一門語言就應(yīng)該有一門語言的樣子。
比如用C,如無絕對必要,就不應(yīng)該模擬出虛函數(shù)與異常機制。
書里面提到的7種優(yōu)勢,除了最后一種值得考慮,其他全都不值得稱作優(yōu)勢。
property,C#中的,或者imperfect cpp 里面看起來的樣子,無非就是讓如下語法:
o.p( value ); o.set_p( value );
value = o.p(); value = o.get_p();
變成如下語法:
o.p = value;
value = o.p;
如果C++直接提供property的語法,那當(dāng)然是好事。
但不提供,也不見得編程就進行不下去了,也沒有絕對必要去模擬出這種東西。
書中提到的7個好處,除了最后1個,其他都不是property帶來的好處。
1. 讀寫控制
非property一樣可以實現(xiàn)讀寫控制
2. 內(nèi)外表示轉(zhuǎn)換
這依然是由Date的算法實現(xiàn),而不是property的功勞。
不通過property,一樣可以實現(xiàn)time_t作為內(nèi)部表示,對外提供int get_xxx()
3. 驗證
這個更搞笑了。
就在書中這句話的下面列出的代碼,就明顯說明對day的驗證是通過:
void Date::set_DayOfMonth(int day);
完成的。
完全沒有property的半分功勞。
4. 沒看太明白
書中的意思是, Date.Now是一個緩存,Date::get_Now()是一個計算?
其實,這里真正需要的是"兩種語意",而不是property。
這兩種語意是:
Date::getNow();
Date::updateNow();
書中只是將getNow的語意,用property來表現(xiàn);get_Now同時完成updateNow和getNow。
5. 可用性?
We didn't have to write date.get_Month(), just date.Month.
少敲點鍵盤而已……
如果利用重載,用void Month(value)代表set,用value Month(void)代表get,少敲的,就是一個調(diào)用操作符……
6. 不變式?
沒看太明白。
沒有property,也可以維護object的不變式,是吧?
只要將數(shù)據(jù)hide,通過public interface去操作,就可以了。
7. 范型編程
我覺得就只有這個說到點子上了。 而這個也就是模擬property的真正的作用:改變語法。
template<typename P>
void distance(const P& p1, const P& p2 ) {
假設(shè)這是一個計算2個點歐式距離的函數(shù)。 它已經(jīng)通過:
p1.x;
這種語法,而不是p1.x(); 這種語法寫成了。
}
如果新實現(xiàn)一個class, 想通過p1.x 這種語法訪問,同時還要有讀寫控制等, 就需要模擬出property。
這可能是property真正的用處。
換句話說,真的存在很多情況,使得我們"不得不"使用如下語法:
o.p = value;
value = o.p;
來代替如下語法:
o.set_p( value );
value = o.get_p();
嗎?
對這種情況,property模擬才是有價值的。
對很多情況,setter/getter的語法和property的語法都是可行的。
如果本身提供了property語法的語言,那使用2者之一都沒關(guān)系。
但C++沒有提供。對這種情況也非要去模擬出property的語法,就有點…… 為了property而property的味道了。
我繼續(xù)去看書中怎么實現(xiàn)的……
我以前了解的實現(xiàn)方式,每一個proxy至少得帶一個指針……
這消耗還是蠻嚴(yán)重的……
你怎么看?
我覺得前面都寫得不錯,ABI、mangling這些問題確實是很困擾……
但property…… 我覺得這并不算C++的Imperfection。
完全是被其他語言給蒙蔽了。
一門語言就應(yīng)該有一門語言的樣子。
比如用C,如無絕對必要,就不應(yīng)該模擬出虛函數(shù)與異常機制。
書里面提到的7種優(yōu)勢,除了最后一種值得考慮,其他全都不值得稱作優(yōu)勢。
property,C#中的,或者imperfect cpp 里面看起來的樣子,無非就是讓如下語法:
o.p( value ); o.set_p( value );
value = o.p(); value = o.get_p();
變成如下語法:
o.p = value;
value = o.p;
如果C++直接提供property的語法,那當(dāng)然是好事。
但不提供,也不見得編程就進行不下去了,也沒有絕對必要去模擬出這種東西。
書中提到的7個好處,除了最后1個,其他都不是property帶來的好處。
1. 讀寫控制
非property一樣可以實現(xiàn)讀寫控制
2. 內(nèi)外表示轉(zhuǎn)換
這依然是由Date的算法實現(xiàn),而不是property的功勞。
不通過property,一樣可以實現(xiàn)time_t作為內(nèi)部表示,對外提供int get_xxx()
3. 驗證
這個更搞笑了。
就在書中這句話的下面列出的代碼,就明顯說明對day的驗證是通過:
void Date::set_DayOfMonth(int day);
完成的。
完全沒有property的半分功勞。
4. 沒看太明白
書中的意思是, Date.Now是一個緩存,Date::get_Now()是一個計算?
其實,這里真正需要的是"兩種語意",而不是property。
這兩種語意是:
Date::getNow();
Date::updateNow();
書中只是將getNow的語意,用property來表現(xiàn);get_Now同時完成updateNow和getNow。
5. 可用性?
We didn't have to write date.get_Month(), just date.Month.
少敲點鍵盤而已……
如果利用重載,用void Month(value)代表set,用value Month(void)代表get,少敲的,就是一個調(diào)用操作符……
6. 不變式?
沒看太明白。
沒有property,也可以維護object的不變式,是吧?
只要將數(shù)據(jù)hide,通過public interface去操作,就可以了。
7. 范型編程
我覺得就只有這個說到點子上了。 而這個也就是模擬property的真正的作用:改變語法。
template<typename P>
void distance(const P& p1, const P& p2 ) {
假設(shè)這是一個計算2個點歐式距離的函數(shù)。 它已經(jīng)通過:
p1.x;
這種語法,而不是p1.x(); 這種語法寫成了。
}
如果新實現(xiàn)一個class, 想通過p1.x 這種語法訪問,同時還要有讀寫控制等, 就需要模擬出property。
這可能是property真正的用處。
換句話說,真的存在很多情況,使得我們"不得不"使用如下語法:
o.p = value;
value = o.p;
來代替如下語法:
o.set_p( value );
value = o.get_p();
嗎?
對這種情況,property模擬才是有價值的。
對很多情況,setter/getter的語法和property的語法都是可行的。
如果本身提供了property語法的語言,那使用2者之一都沒關(guān)系。
但C++沒有提供。對這種情況也非要去模擬出property的語法,就有點…… 為了property而property的味道了。
我繼續(xù)去看書中怎么實現(xiàn)的……
我以前了解的實現(xiàn)方式,每一個proxy至少得帶一個指針……
這消耗還是蠻嚴(yán)重的……
你怎么看?
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-15 18:58
@cexer
沒有完整的,就是你blog上發(fā)的一些片段……
沒有完整的,就是你blog上發(fā)的一些片段……
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-15 18:57
@cexer
哦 原來是property模擬。
window.size
window.onCreated
是一個,呃,代理(proxy)對象?
size是一個代理,有一個=操作符和轉(zhuǎn)換函數(shù):
operator=(const Size& s) {
this->window->setSize(s);
}
operator Size() const {
return this->window->getSize();
}
這個代理對象也是要占空間的吧?
呃…… 還是等你的源代碼與分析吧…… 不瞎猜了……
看來你也是難得抓到一個更新blog的閑暇……
哦 原來是property模擬。
window.size
window.onCreated
是一個,呃,代理(proxy)對象?
size是一個代理,有一個=操作符和轉(zhuǎn)換函數(shù):
operator=(const Size& s) {
this->window->setSize(s);
}
operator Size() const {
return this->window->getSize();
}
這個代理對象也是要占空間的吧?
呃…… 還是等你的源代碼與分析吧…… 不瞎猜了……
看來你也是難得抓到一個更新blog的閑暇……
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-15 18:40
從這2行代碼來說:
window.onCreated.add( &_handleCreated );
window.onCreated.clear();
從UINT message 到 onCreate 的這個分派(dispatch)過程,無論怎樣都必定是一個運行時解析過程。
無論使用何種C++高級技巧,也不可能讓它變?yōu)榫幾g時dispatch。
因為message是一個運行時才能得到的值……
只是,這個dispatch的工作,可能不是由window所在的class完成,而是其他某個層次完成。
總之,這個層次一定存在,這個工作(運行時dispatch)一定免不了。
我猜得對嗎……
接下來,框架將message 分派到onXXX之后,客戶再將onXXX轉(zhuǎn)發(fā)(forwarding)自己的handler這個過程,我相信是可以編譯時確定的。
——因為我看過你以前的一些實現(xiàn)~_~
但是,編譯時確定,就意味著運行時不可更改。
如果要運行時可更改 —— 如上面2行代碼 —— 就一定需要一個"可調(diào)用體"(callable)來作handler的占位符(placeholder)。
是這樣嗎?
而C/C++里面,完全不占用一點空間的callable…… 是不存在的,對吧?
所以我很好奇window是如何零成本完成映射與轉(zhuǎn)發(fā),并且是一個空對象的。
映射肯定需要在某個地方做,可能不是window。
運行時可更改轉(zhuǎn)發(fā)目的地而不使用數(shù)據(jù), 好像…… 太不可思議了……
window.onCreated.add( &_handleCreated );
window.onCreated.clear();
從UINT message 到 onCreate 的這個分派(dispatch)過程,無論怎樣都必定是一個運行時解析過程。
無論使用何種C++高級技巧,也不可能讓它變?yōu)榫幾g時dispatch。
因為message是一個運行時才能得到的值……
只是,這個dispatch的工作,可能不是由window所在的class完成,而是其他某個層次完成。
總之,這個層次一定存在,這個工作(運行時dispatch)一定免不了。
我猜得對嗎……
接下來,框架將message 分派到onXXX之后,客戶再將onXXX轉(zhuǎn)發(fā)(forwarding)自己的handler這個過程,我相信是可以編譯時確定的。
——因為我看過你以前的一些實現(xiàn)~_~
但是,編譯時確定,就意味著運行時不可更改。
如果要運行時可更改 —— 如上面2行代碼 —— 就一定需要一個"可調(diào)用體"(callable)來作handler的占位符(placeholder)。
是這樣嗎?
而C/C++里面,完全不占用一點空間的callable…… 是不存在的,對吧?
所以我很好奇window是如何零成本完成映射與轉(zhuǎn)發(fā),并且是一個空對象的。
映射肯定需要在某個地方做,可能不是window。
運行時可更改轉(zhuǎn)發(fā)目的地而不使用數(shù)據(jù), 好像…… 太不可思議了……
re: GUI框架:談?wù)効蚣埽瑢憣懘a OwnWaterloo 2009-11-15 18:21
占個沙發(fā),對這個很好奇:
"值得說一下,這種神奇的映射者是接近零成本的,它沒有數(shù)據(jù)成員沒有虛函數(shù)什么都沒有,就是一個簡單的空對象。就像傳說中的工作能力超強,但卻不拿工資,不泡公司MM,甚至午間盒飯也不要的理想職員。"
"值得說一下,這種神奇的映射者是接近零成本的,它沒有數(shù)據(jù)成員沒有虛函數(shù)什么都沒有,就是一個簡單的空對象。就像傳說中的工作能力超強,但卻不拿工資,不泡公司MM,甚至午間盒飯也不要的理想職員。"
re: 輸入流函數(shù)模板決議問題導(dǎo)致程序不簡潔 OwnWaterloo 2009-11-15 03:54
沒辦法…… 讓它吃點虧好了:
template <typename DataStream>
DataStream& operator>>(DataStream& a_data, A& a_fileHeader);
該成這樣:
template<typename C,class T>
std::basic_istream<C,T>& operator>>(std::basic_istream<C,T>& s,A& a);
這也是為iostream寫擴展時要考慮的一個問題:
1. 要么嚴(yán)格使用標(biāo)準(zhǔn)庫中的(w)i(f/string)stream,basic_i(f/string)stream
2. 要么放寬,使用任意重載了>>的。
二進制和文本關(guān)系到是否轉(zhuǎn)換換行模式。
寫入文件時是怎么寫的?
>>和<<是格式化輸出。
read/write是非格式化輸出。
12
<<結(jié)果就是 '1','2' , >>時也希望是這樣
write結(jié)果就是 0c,00,00,00, read時也希望是這樣。
template <typename DataStream>
DataStream& operator>>(DataStream& a_data, A& a_fileHeader);
該成這樣:
template<typename C,class T>
std::basic_istream<C,T>& operator>>(std::basic_istream<C,T>& s,A& a);
這也是為iostream寫擴展時要考慮的一個問題:
1. 要么嚴(yán)格使用標(biāo)準(zhǔn)庫中的(w)i(f/string)stream,basic_i(f/string)stream
2. 要么放寬,使用任意重載了>>的。
二進制和文本關(guān)系到是否轉(zhuǎn)換換行模式。
寫入文件時是怎么寫的?
>>和<<是格式化輸出。
read/write是非格式化輸出。
12
<<結(jié)果就是 '1','2' , >>時也希望是這樣
write結(jié)果就是 0c,00,00,00, read時也希望是這樣。
re: 函數(shù)調(diào)用棧初探 OwnWaterloo 2009-11-15 03:33
調(diào)試器需要符號表。
re: Concept 被移除,無緣 C++ 0x OwnWaterloo 2009-11-15 02:34
依然可以算C++0x……
0x嘛,大家都知道是16進制……
明年是C++0a,后年是C++0b ...
0x嘛,大家都知道是16進制……
明年是C++0a,后年是C++0b ...
re: SFINEA in C++ OwnWaterloo 2009-11-15 02:33
現(xiàn)在和cnblogs的格式很相似了。
Windows Live Wirter可以導(dǎo)入pdf,然后發(fā)布到blog么?
或者Windows Live Writer在本地使用的什么格式? 可以diff(主要目的)么……
我有個想法是用某種文本文件格式的代碼,比如html,latex,rst等,生成可以導(dǎo)入到Windows Live Writer的格式,再發(fā)布。
文本格式的代碼可以diff……
Windows Live Wirter可以導(dǎo)入pdf,然后發(fā)布到blog么?
或者Windows Live Writer在本地使用的什么格式? 可以diff(主要目的)么……
我有個想法是用某種文本文件格式的代碼,比如html,latex,rst等,生成可以導(dǎo)入到Windows Live Writer的格式,再發(fā)布。
文本格式的代碼可以diff……
| |||||||||
| 日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
|---|---|---|---|---|---|---|---|---|---|
| 26 | 27 | 28 | 29 | 30 | 31 | 1 | |||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 | |||
| 9 | 10 | 11 | 12 | 13 | 14 | 15 | |||
| 16 | 17 | 18 | 19 | 20 | 21 | 22 | |||
| 23 | 24 | 25 | 26 | 27 | 28 | 29 | |||
| 30 | 1 | 2 | 3 | 4 | 5 | 6 | |||
常用鏈接
留言簿(8)
隨筆檔案(16)
鏈接
- ownwaterloo on vckbase

- 在vckbase上的博客,已停止使用。
- wargrey
搜索
積分與排名
- 積分 - 199014
- 排名 - 134
最新隨筆
最新評論

- 1.?re: C與C++的細(xì)微區(qū)別——省略形式參數(shù)名
- 看了你的分析解決了困擾我很久的問題,太感謝啦!!!
- --j5682809
- 2.?re: C與C++的細(xì)微區(qū)別——省略形式參數(shù)名
- 好厲害!gcc就遇到wunused 錯誤,謝謝~
- --cjj
- 3.?re: main函數(shù)中省略返回語句[未登錄]
- LOL
- --null
- 4.?re: 預(yù)定義_MSC_VER宏[未登錄]
- 很好的文章,轉(zhuǎn)載一下,謝謝。。。^_^
- --lance
- 5.?re: 可變長參數(shù)列表誤區(qū)與陷阱——va_arg不可接受的類型[未登錄]
- 干嗎要把float提升到double,就差沒有想到這一條,害我調(diào)試了半天。。float一般不是4個自己嗎?也算int對齊的呀,真奇怪。
- --alex
