青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 16,  comments - 34,  trackbacks - 0
共10頁: First 2 3 4 5 6 7 8 9 10 
@visualfc
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é),大致想的時候會被忽略。

@空明流轉(zhuǎn)
好東西啊,好東西,看得我心花怒放~_~
再次感謝~_~


順便也感謝一下cexer。
果然是【閱盡MFC,WTL,SmartWin++,win32gui,jlib2 ,VCF ;看盡天下 GUI 的感覺。】

果然只看示例和書不寫代碼是不行的。就書上的示例代碼,我還領(lǐng)會不了其精髓……
其實也不是我不想寫…… 我寫過一些……
然后就沒機會寫了……

@空明流轉(zhuǎn)
我靠!還有這種工具!
太感謝了~_~

其實我也不做什么的啦……
主要是寫文檔(設(shè)計文檔、博客)的時候染染色啦……
@陳梓瀚(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還是很強大的……

@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的需求",可以用普通繼承改寫的例子。


這樣理解如何?


@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"?

@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)生鏈接錯誤。
};

是這樣嗎?

@陳梓瀚(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)該會好很多……

@陳梓瀚(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)自銷。


你覺得這個提議怎樣?

@陳梓瀚(vczh)
如何在屬性實現(xiàn)狀態(tài)變化控制的技術(shù)嘛,沒有說過命名……看來我們是互相誤解了啊…… 

那你也說說你的想法嘛……
比如那個“效率問題”應(yīng)該怎么理解?

有人說可以拿C/C++程序員作巴浦洛夫?qū)嶒灒刺岬?效率"2字時他們是否會流口水……

我沒有流口水…… 但是我很好奇……

@cexer
管飯的人呢……

這問題反復(fù)困擾我很久了…… 一直沒得到解答…… 于是塵封了……
用ATL/WTL的人很少,問都找不到人問……
今天終于找到管飯的了, 一定得追問到底~_~

@陳梓瀚(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繼承,還有什么好處么……
一開始,我也覺得很神奇…… 后來越想越不是那么回事…… 然后一直沒想通……

@陳梓瀚(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。

@陳梓瀚(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ì)說說你的需求么?
@cexer
ATL-style繼承,提供的語意是:
基類提供默認(rèn)實現(xiàn),派生類繼并覆蓋自己需要的函數(shù)。
是這樣嗎?
除了這個,還有其他功能嗎?

但這個功能,不正好就是非ATL-style繼承 —— 普通繼承提供的語意嗎……
為什么要繞這么大一個圈子?
能得到什么好處? header-only?

@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"


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ì)一點?

【我跟OwnWaterloo就借著你的地盤版聊了哈】

要不我們開一個論壇吧?google groups或者群?
群的聊天資料可能不容易搜出來……

toplangauge越來越水了……

把cppblog上的人都招集起來?

很高興和你們討論問題~_~
如果我語氣有過激之處,請不吝指出,或者多多包涵一下。

有人響應(yīng)沒……?

【我并沒有反對你優(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。
我真的沒看明白你說的那個需求是什么…… 囧


【行為指的是受改變的時候發(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。

【【窄化】不是問題。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)化。

【至于其他的例子,你可以參考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。

【其實舉過了嘛,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)看太多,說不定大家都知道,我又何必多次一舉?
而且很多都不是我獨立想出來的。
所以我覺得說出來很掉價……

"當(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)心。
這樣的點,就需要行為。

"模擬屬性一點都不無聊,因為一個可以監(jiān)聽和撤銷屬性變化的系統(tǒng)非常容易擴展,總比你一個類都來一個listener或者就像api一樣所有的消息的格式都很混亂的好。特別對于開發(fā)GUI的庫。當(dāng)然這就不僅僅是如何響應(yīng)operator=的問題了。允許阻止變化的listener總是有開銷的,所以你無法杜絕它。這也是我第一次舉例子的時候就說出來的一個可以認(rèn)為是“需求”的東西。"

模擬屬性就是很無聊的工作。
你試著回答一個問題:”這里一定需要operator=嗎? 可以使用命名函數(shù)嗎?
如果回答是“是” ,那這里就寧可采用命名函數(shù),而不是屬性。
絕大部分回答都應(yīng)該是“是”。所以這根本不算一個需求。


從我的直覺上來說,模擬屬性使用的價值并不大。沒有多少場合非屬性不可
如果你可以想到一個“不是”的例子,請列舉出來。
也許我的直覺是錯的。

"模擬屬性一點都不無聊,因為一個可以監(jiān)聽和撤銷屬性變化的系統(tǒng)非常容易擴展,總比你一個類都來一個listener或者就像api一樣所有的消息的格式都很混亂的好。特別對于開發(fā)GUI的庫。當(dāng)然這就不僅僅是如何響應(yīng)operator=的問題了。允許阻止變化的listener總是有開銷的,所以你無法杜絕它。這也是我第一次舉例子的時候就說出來的一個可以認(rèn)為是“需求”的東西。"

模擬屬性就是很無聊的工作。
你試著回答一個問題:”這里一定需要operator=嗎? 可以使用命名函數(shù)嗎?
如果回答是“是” ,那這里就寧可采用命名函數(shù),而不是屬性。
絕大部分回答都應(yīng)該是“是”。所以這根本不算一個需求。


從我的直覺上來說,模擬屬性使用的價值并不大。沒有多少場合非屬性不可
如果你可以想到一個“不是”的例子,請列舉出來。
也許我的直覺是錯的。

"舉個簡單的例子,總線形式的開發(fā)會讓string有一個c_str(),而不是讓string消失。我不知道你知不知道解決方案是什么樣子的,但是舉個例子出來總是要告訴別人說,“哦,這個東西可以這么這么做,只是我懶的寫完整”而不是沒說完。"

我相信看的人能明白我代碼中的重點在那里。
我不明白的是你為何看不明白,即使在我說了之后。

我再說一下吧,如果要讓我說"這個property"還可以這樣玩、又可以那樣玩,我會覺得很掉價……
一方面因為我現(xiàn)在本來就不喜歡過分玩弄語言特性。
另一方面,這些技術(shù)實在是說得太多……


如果一定要把所有細(xì)節(jié)都展現(xiàn)出來,不知道評論的字?jǐn)?shù)會不會夠。
而且,展現(xiàn)到什么程度才可以停止?

@陳梓瀚(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引用上。

@陳梓瀚(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)化了。

@陳梓瀚(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ā)代價的直連線形式。

@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


我再想想……


@陳梓瀚(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#?好好想想吧。

@陳梓瀚(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)無聊……


這一點不知道你看出來了沒?
@陳梓瀚(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ù)深入了一下。
re: SFINEA in C++ OwnWaterloo 2009-11-16 03:58
@唐風(fēng)
我試試 …… 謝謝~_~

關(guān)于隱藏time_成員……
 
1.
class C
{
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就可能會被填充
};
 
 
仔細(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;
                // ...
        }
};
 
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;
        }
        // ...
};
 
這樣,客戶代碼可以訪問的,只有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.
范化工作 
這個…… 再說吧……
 如果能有更好的布局方案…… 范化工作就白做了……
 
@cexer
關(guān)鍵點在于:"如何通過proxy地址,得到object地址"。
 
1. 可以給proxy放入一個object的指針。每個proxy消耗一個指針的空間。
太浪費了……
 
2. Imperfect C++中利用offset來計算object的地址,使得每個proxy不含任何域。
但C++為了區(qū)別各個proxy,會給每個proxy進行填充,依然會造成消耗。
 
 
3. 避免proxy在Record中被填充
假設(shè)有如下記錄:
Record
{
        proxy1 property1;
        proxy2 property2;
        proxy3 property3;
        ...
}
其中proxy1,proxy2,proxy3, ...  是空結(jié)構(gòu)。
 
Record r;
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 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);
        }
};

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_;   什么都完蛋了……
 
 
我再想想怎么隱藏……
 
@cexer
我想到一個幾乎沒有消耗的方案……
我再完善一下……

@cexer
Imperfect C++中的差不多看明白了……
proxy是包含在object中,通過proxy在object中的offset得到object的地址……


我暈……
侵入式的property……

強大……

我去看了看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)重的……


你怎么看?
@cexer
沒有完整的,就是你blog上發(fā)的一些片段……

@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的閑暇……

從這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ù), 好像…… 太不可思議了……


占個沙發(fā),對這個很好奇:

"值得說一下,這種神奇的映射者是接近零成本的,它沒有數(shù)據(jù)成員沒有虛函數(shù)什么都沒有,就是一個簡單的空對象。就像傳說中的工作能力超強,但卻不拿工資,不泡公司MM,甚至午間盒飯也不要的理想職員。"

沒辦法…… 讓它吃點虧好了:
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 ...

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……

共10頁: First 2 3 4 5 6 7 8 9 10 
<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

常用鏈接

留言簿(8)

隨筆檔案(16)

鏈接

搜索

  •  

積分與排名

  • 積分 - 199014
  • 排名 - 134

最新隨筆

最新評論

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲一区免费网站| 亚洲国产日韩欧美在线图片| 久久gogo国模裸体人体| 欧美亚洲日本国产| 午夜精品久久久久久久久久久久久 | 亚洲第一区色| 久久综合亚州| 欧美成人影音| 亚洲精品免费一二三区| 一本色道久久综合| 午夜精品影院在线观看| 久久综合五月天婷婷伊人| 欧美激情综合五月色丁香| 欧美日韩视频专区在线播放 | 久久久夜色精品亚洲| 欧美激情亚洲另类| 国产精品日韩在线| 亚洲国内高清视频| 午夜国产不卡在线观看视频| 老妇喷水一区二区三区| 一区二区三区高清在线| 久久精品电影| 欧美午夜电影网| 亚洲激情在线播放| 欧美一级一区| 亚洲精品中文字幕女同| 久久精品卡一| 国产精品九九| 亚洲精品一区二区三区99| 欧美在线一二三四区| 亚洲精品久久久久久下一站| 欧美自拍偷拍| 国产精品老牛| 一本色道久久加勒比精品| 久久综合九色九九| 亚洲欧美日本日韩| 欧美色中文字幕| 亚洲免费观看视频| 亚洲国产高清一区| 久久久久亚洲综合| 国产婷婷成人久久av免费高清 | 亚洲国产欧美日韩| 亚洲欧美日韩一区| 欧美日韩午夜在线视频| 亚洲欧洲在线看| 久久综合中文字幕| 欧美一区二区三区在线看| 欧美小视频在线| 一区二区不卡在线视频 午夜欧美不卡在 | 欧美日韩1080p| 亚洲黄色精品| 狂野欧美激情性xxxx欧美| 午夜亚洲视频| 国产视频在线观看一区| 欧美在线亚洲| 久久er精品视频| 伊人精品成人久久综合软件| 久久精品最新地址| 欧美在线啊v一区| 狠狠爱综合网| 媚黑女一区二区| 模特精品裸拍一区| 亚洲人成网在线播放| 亚洲成色最大综合在线| 欧美激情第10页| 亚洲无线视频| 亚洲影院色在线观看免费| 国产精品欧美久久| 久久精品国产亚洲a| 欧美在线观看视频| 亚洲国产天堂久久国产91| 亚洲第一网站| 欧美日韩裸体免费视频| 亚洲午夜电影| 欧美一区二区黄| 亚洲国产精品va在线看黑人| 欧美激情一区二区三区在线| 欧美日韩www| 欧美在线亚洲一区| 美日韩在线观看| 亚洲一区二区精品在线| 欧美在线亚洲在线| 亚洲美女黄网| 亚洲欧美日韩一区| 91久久在线视频| 亚洲午夜伦理| 亚洲国产精品高清久久久| 日韩视频在线观看国产| 国产一区二区三区在线观看免费| 欧美成人乱码一区二区三区| 欧美日韩综合视频网址| 久久久水蜜桃av免费网站| 另类欧美日韩国产在线| 在线视频你懂得一区| 久久精品国产第一区二区三区最新章节| 在线看不卡av| 亚洲午夜91| 亚洲三级免费电影| 欧美亚洲综合另类| 中文高清一区| 欧美a级片网| 国产精品乱码人人做人人爱| 美国十次了思思久久精品导航| 欧美日韩国产综合一区二区| 狼狼综合久久久久综合网| 国产精品国产a| 亚洲国产日韩一区二区| 国产在线麻豆精品观看| 夜夜爽av福利精品导航 | 亚洲欧洲一区二区三区在线观看 | 久久精品视频在线| 亚洲男人第一av网站| 欧美成人精品高清在线播放| 久久九九精品| 欧美日韩综合不卡| 亚洲精品在线免费观看视频| 亚洲国产精品一区制服丝袜| 香蕉av福利精品导航| 亚洲天堂免费观看| 欧美精品 日韩| 91久久线看在观草草青青| 国产一区二区三区电影在线观看| 日韩视频一区二区三区| 一本色道久久综合| 欧美激情一级片一区二区| 欧美成人精品福利| 尤物yw午夜国产精品视频明星 | 久久阴道视频| 久久免费高清视频| 激情综合色综合久久综合| 羞羞色国产精品| 欧美中文字幕在线| 国产欧美午夜| 久久成人精品| 久久男女视频| 激情综合电影网| 蜜桃精品久久久久久久免费影院| 欧美jjzz| 日韩一级视频免费观看在线| 欧美国产一区二区在线观看| 亚洲国产欧美日韩| 亚洲一区二区三| 国产日韩欧美精品综合| 欧美在线视频a| 美日韩丰满少妇在线观看| 亚洲国产精品va在看黑人| 欧美大尺度在线观看| 亚洲精品一区中文| 亚洲午夜在线观看| 国产欧美日韩免费| 久久精品电影| 91久久亚洲| 香蕉久久夜色精品国产使用方法| 国产精品人人做人人爽| 亚欧成人在线| 亚洲国产毛片完整版 | 亚洲视频香蕉人妖| 国产精品亚洲美女av网站| 午夜视频一区| 亚洲福利专区| 国产精品一区在线观看你懂的| 午夜精品久久久久久久99水蜜桃| 亚洲欧美不卡| 午夜精品短视频| 国语自产偷拍精品视频偷| 欧美顶级大胆免费视频| 一本色道**综合亚洲精品蜜桃冫| 香蕉久久一区二区不卡无毒影院 | 性做久久久久久久免费看| 欧美大片在线观看一区| 亚洲视频免费| 亚洲第一网站免费视频| 欧美日韩日日骚| 久久精彩免费视频| 一区二区电影免费在线观看| 久久综合激情| 亚洲综合国产| 亚洲精品一区二区网址 | 亚洲一区在线视频| 红桃视频国产精品| 欧美性猛交视频| 麻豆精品在线观看| 午夜精品久久久久久久白皮肤| 亚洲国产免费看| 久久久亚洲成人| 亚洲一二三区视频在线观看| 韩国一区二区三区在线观看| 欧美体内谢she精2性欧美 | 欧美日韩在线三区| 久久综合色婷婷| 欧美在线播放视频| 中文日韩在线视频| 欧美激情第10页| 久久综合久色欧美综合狠狠 | 久久久久久综合| 亚洲在线观看免费| 亚洲美女尤物影院| 亚洲国产精品成人va在线观看| 久久久久久国产精品mv| 欧美一区二区三区免费在线看|