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

sherrylso

C++博客 首頁 新隨筆 聯系 聚合 管理
  18 Posts :: 0 Stories :: 124 Comments :: 0 Trackbacks

        C++之父Bjarne stroustrup曾經說過:不需要了解所有的c++細節,也能夠寫出好的c++程序;不應該注重語言方面的特征,而應該注重軟件設計技術本身。很顯然,我的這篇文章,與這兩句話背道而馳:).的確,我們程序員,不應該把精力放在c++本身語言的特征上,而是應該思考軟件設計技術本身。那么,在我們需要提高對c++理解的同時,是不是我們從下面幾個方面為著眼點
1) 從編譯原理的角度
2) 從技術需求的角度
3) 從軟件設計技術的角度
從以上的幾個角度,來重新審視c++一些晦澀語法,或許,我們能從中獲益。在這里,我要說的是,我們不單單是要記住這些c++語言特性怎么樣的使用,而是應該知道這些語言特性背后隱藏的故事,以便于我們更深層次地理解c++,理解軟件設計。
一、子類通過函數名字隱藏父類函數。
如下例:

class Base
{
public:
 virtual 
void f(int x);
}
;
class Derived: public Base
{
public:
 virtual 
void f(double* pd);
}
;
int main()
{
  Derived
* pd = new Derived();
  pd
->f(10); //compile error!!!
}

         當我們編譯pd->f(10)操作時,編譯器報錯。按照我們常規的理解是:父類的函數void f(int x)與子類的函數void f(double*pd),由于參數類型不同,其函數簽名也是不一樣的,按照這樣的邏輯,在這個類繼承體系中,這兩個函數完全應該是互不隱藏的,我們完全可以認為是符合overloaded規則的兩個函數。
        但是,在c++里,子類通過函數名字隱藏父類函數,而不是通過函數簽名!c++給出的解釋也是合理的:試想一種情況:你使用了別人寫的類庫,繼承其中的某個類,寫了你自己的子類。
如上面的例子,你的子類就是Derived,而類庫中的父類就是Base.當你根本不知道在父類中還有這樣一個f(int x)函數時,在調用子類Derived的f函數時,你犯了錯誤,參數類型傳成了int類型(或者不是你犯的錯誤,編譯器幫你自動轉化為int類型),結果是:程序可以正常運行,但是,執行的結果卻不是你所期望的,是f(int x)調用,而不是你自己的實現:f(double* pd)調用!
         這就是c++為什么通過函數名字隱藏父類函數的原因。
        說到這里,我們需要補充幾句:雖然c++在語言層面上給我們提供了這樣的保證,但是,子類hide父類的函數,這是一個非常不好的設計。從OO的角度出發,應該講求的是Liskov Substitution Principle。即:suntypes must be substitutable fro their base types.很顯然,當hide行為發生時,從接口的角度來講,子類與父類是不能互為替代的。父類的protected or public的方法,應該很自然地由其所有子類所繼承,而不是被隱藏。隱藏行為的發生,相當于在這套繼承體系中開的一個后門。很顯然,C++幫助我們自動隱藏了父類的方法,但是,作為程序開發的我們,應該意識到這一點,也應該避免這樣的設計。
二、c++的per-class allocator語法規則
          在D&E of C++一書中,Stroustrup給出了幾點c++提供per-class allocator的理由,這些理由也是我們使用class level的allocator的原因,所以,有必要我們總結一下:
第一、許多程序應用,需要在運行的過程中,大量地Create和Delete對象。這些對象,諸如:tree nodes,linked list nodes,messages等等。如果在傳統的heap完成這些對象的創建,銷毀,由于大量的內存申請,釋放,勢必會造成內存碎片。這種情況下,我們需要對內存分配進行細粒度的控制。
第二、一些應用需要長時間跑在內存受限的裝置上,這也需要我們對內存分配進行細粒度的控制,而不是無限制地分配,釋放。
主要基于以上的兩點,c++提供了per-class allocator語言支持。
如下例:

class X
{
public:
  
void* operator new(size_t sz); //allocate sz bytes
  void  operator delete(void* p) //free p;
}
;

      new操作符函數負責對象X的內存分配。對這樣一個語法規則,我們好奇的是,為什么聲明了一個我們從來都不使用的參數size_t sz.我們的使用語法如下: X* px = new X;
C++也給出了解釋:per-class allocator機制將適用整個類的繼承體系。例如:

class Y: public X //ojects of class Y are also allocated using X::operator new
{
  
//
  
// 
}
;

        對于子類Y,其內存分配函數也是X::operator new()。但是,在這里,內存分配的大小,不應該是sizeof(X),而是sizeof(Y).問題的關鍵在這里:C++通過提供多余的參數size_t sz,而給開發者提供了更大的靈活性,也即:per-class allocator是面向類的繼承體系的內存管理機制,而不單單是面向單個類。
三、Koenig Lookup機制。
        大家對Andrew Koenig應該很熟悉,c++大牛,是AT&T公司Shannon實驗室大規模編程研究部門中的成員,同時他也是C++標準委員會的項目編輯。他擁有超過30年的編程經驗,其中有15年的C++使用經驗。
        Koenig Lookup,就是以Andrew Koenig命名的查找規則。在看這個定義之前,我們先弄清楚函數所在的域的分類,一般來講,分為:
1:類域(函數作為某個類的成員函數(靜態或非靜態))
2:名字空間域
3:全局域(即C++默認的namespace)
        而Koenig Lookup機制,就是當編譯器對無限定域的函數調用進行名字查找時,除了當前名字空間域以外,也會把函數參數類型所處的名字空間加入查找的范圍。
如下例:

#include <iostream>
using namespace std;
namespace Koenig
{
    
class MyArg
    
{
    
public:
         ostream
& print(ostream& out) const
         
{
            out
<<"this is MyArg."<<endl;
         }

    }
;
 
    inline ostream
& operator<<(ostream& out, const MyArg& myArg)
    
{
         
return myArg.print(out);
    }

}

 
int main()
{
    Koenig::MyArg myArg;
    cout
<<myArg;
    
return 0;
}

       如上的代碼,使用operator<<操作符函數,打印對象的狀態,但是函數ostream& operator<<(ostream& out, const MyArg& myArg) 的定義域是處于名字空間Koenig中,為什么編譯器在解析main函數(全局域)里面的operator<<調用時,它能夠正確定位到Koenig名字空間里面的operator<<?這是因為根據Koenig查找規則,編譯器需要把參數類型MyArg所在的名字空間Koenig也加入對ostream& operator<<(ostream& out, const MyArg& myArg) 調用的名字查找范圍中。
       
如果沒有Koenig查找規則,我們就無法直接寫cout<<myArg;,而是需要寫類似Koenig::operator<<(std::cout, myArg); 這樣的代碼(使用完全限定名)。這樣的結果是,即不直觀也不方便。

        其實在C++里,提供了很多類似于Koenig查找規則的機制,以保證程序語法上的簡潔,明了。例如:許多的操作符函數,COPY構造函數。而這些,也是我們寫出專業的C++程序的基本。
未完待續:)

 

 


 

posted on 2007-11-11 14:56 愛上龍卷風 閱讀(4676) 評論(26)  編輯 收藏 引用

Feedback

# re: c++晦澀語法背后的故事(一) 2007-11-11 15:16 lovedday
關于

class Base
{
public:
virtual void f(int x);
};
class Derived: public Base
{
public:
virtual void f(double* pd);
};
int main()
{
Derived* pd = new Derived();
pd->f(10); //compile error!!!
}

很顯然編譯報錯是對的,因為函數原型不一樣,所以不構成overwrite。

既然不構成overwrite,那么你調用的就是Derived中的f函數,編譯器檢查后發現沒有匹配的函數,當然報錯。

至于后面的解釋個人認為不著調。  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-11-11 15:25 <a href=http://minidx.com>minidxer</a>
同意lovedday的觀點  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-11-11 15:25 lovedday
#include <iostream>
using namespace std;
namespace Koenig
{
class MyArg
{
public:
ostream& print(ostream& out) const
{
out<<"this is MyArg."<<endl;
}
};

inline ostream& operator<<(ostream& out, const MyArg& myArg)
{
return myArg.print(out);
}
}

int main()
{
Koenig::MyArg myArg;
cout<<myArg;
return 0;
}

這種代碼基本上屬于濫用運算符重載,實際上C++的不少機制都會導致被濫用,結果就是產生晦澀難懂且充滿bug的垃圾代碼,當然這種代碼做為反面教材還是不錯的,但若是在項目中使用這種代碼,那將是惡夢。
  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-11-11 15:29 lovedday
個人認為盡量少重載運算符,比如printf就比<<好用,實在沒有什么必要去重載<<,使用函數更好。  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-11-11 15:34 lovedday
ps,說這些沒別的意思,只是說在實際項目中不應該這么使用運算符重載,當然sherrylso只是為了說明C++語法而編寫這些代碼。  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-11-11 15:37 lovedday
C++里還有函數重載和參數默認值,實際上這兩個機制是滋生bug的溫床,如果配合多態,將會導致十分難以理解的行為,所以別用函數重載和參數默認值。

看看這個例子,絕對讓你抓狂,猜猜看輸出的i和j值是多少?

#include <stdio.h>

class PARENT
{
public:
virtual int doIt( int v, int av = 10 )
{
return v * v;
}
};

class CHILD : public PARENT
{
public:
int doIt( int v, int av = 20 )
{
return v * av;
}
};

int main()
{
PARENT *p = new CHILD();

int i = p->doIt(3);
printf("i = %d\n", i);

CHILD* q = new CHILD();

int j = q->doIt(3);
printf("j = %d\n", j);

return 0;
}  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-11-11 16:20 foobar
@lovedday
class Base
{
public:virtual void f(int x);
};
class Derived: public Base
{
public:virtual void f(double* pd);
};
int main()
{
Derived* pd = new Derived();
pd->f(10); //compile error!!!
}

這個例子只有聲明沒有定義,編譯肯定有錯
但是
在c++里,子類通過函數名字隱藏父類函數,而不是通過函數簽名!

這個分析應該沒什么問題
子類確實通過函數名字隱藏了父類的函數
  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-11-11 16:38 lovedday
在c++里,子類通過函數名字隱藏父類函數,而不是通過函數簽名!

這個分析應該沒什么問題
子類確實通過函數名字隱藏了父類的函數

-------------------------------------------------------

你的這個論斷顯然是錯的。

#include <stdio.h>

class Base
{
public:
virtual void f(int x)
{
printf("call base f function\n");
}
};

class Derived: public Base
{
public:
virtual void f(double pd)
{
printf("call derived f function\n");
}
};

int main()
{
Base* pb = new Derived;
pb->f(10.5);

return 0;
}

輸出:

call base f function  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-11-11 16:47 foobar
@lovedday
pb是個父類指針,所以調用父類的f

Derived* pb = new Derived;
pb->f(10);
  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-11-11 17:00 lovedday
@foobar

很懷疑你是不是C++沒學好。  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-11-11 17:05 lovedday
#include <stdio.h>

class Base
{
public:
virtual void f(int x)
{
printf("call base f function\n");
}
};

class Derived: public Base
{
public:
virtual void f(double pd)
{
printf("call derived f function\n");
}
};

int main()
{
Base* pb = new Derived;
pb->f(10.5);

return 0;
}

輸出:

call base f function

你說只要函數名稱相同子類就可以覆蓋父類函數的行為,但很顯然,這個例子說明了僅函數名稱相同是無法覆蓋的。如果你沒看懂,是不是說明還沒把多態搞清楚?  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-11-11 17:07 foobar
@lovedday
上面說的不夠確切
你c++學的好,知道多態這個概念,但是c++有很多缺點
樓主的那個例子,你在理解上是有誤的
子類的確實用函數簽名hide了父類的函數
所以你調用f的時候,肯定調用了f(double)

但是用dynamic type的時候,情況就不是這樣了

nt main()
{
Base* pb = new Derived;
pb->f(10.5);

return 0;
}

輸出當然是base
但是絕對不是子類有個函數輸出base
而確實調用了父類的函數

  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-11-11 17:10 foobar
@lovedday
多態是c++的一個特性 但是 c++遠比這個復雜
你看看下面的代碼,希望能明白我的意思

#include <iostream>
class Base
{
public:
virtual void foo() { std::cout << "Base::foo\n"; }
void foo(int) { std::cout << "Base::foo(int)\n"; }
};

class Derived : public Base
{
public:
void foo() { std::cout << "Derived::foo\n"; }
};

int main()
{
Base b;
b.foo(); // Base's foo() is called
b.foo(3); // Base's foo(int) is called
Derived d;
d.foo(); // Derived's foo() is called. The one in Base is hidden
d.foo(3); // error, that function is also hidden
Base &ref = d;
ref.foo(); // Derived's foo() is called. It overrides the Base version
ref.foo(3); // Base's foo(int) is called
}  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-11-11 17:45 lovedday
@foobar

謝謝,我明白了作者的意思,但實際上正如文章所指出的那樣,這是一個糟糕的設計,實際上這些都導致了含混不清的語義和容易出錯的代碼,所以我說不要去重載函數。

C++的復雜很大一部分原因是因為其糟糕的設計。  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-11-12 12:50 pzy
我想可以這么總結:
派生類中的函數會override基類中與它具有相同簽名的虛函數,同時會hide基類中所有與它具有相同名稱(而非簽名)的非虛函數。無論如何,派生類函數不會overload基類函數。

lovedday提供的那個例子(參數默認值)的結果實在是匪夷所思,仿佛此時參數默認值也是簽名的一部分。誰能解釋一下???  回復  更多評論
  

# re: c++晦澀語法背后的故事(一)[未登錄] 2007-11-14 00:43 romangol
@pzy
下面是對應函數調用的反匯編代碼中重要的幾行
int i = p->doIt(3);
0040133B MOV DWORD PTR SS:[ESP+8],0A ;壓入默認參數10
00401343 MOV DWORD PTR SS:[ESP+4],3 ;壓入調用參數3
0040134E MOV DWORD PTR SS:[ESP],EAX
00401351 MOV EAX,DWORD PTR DS:[EDX]
00401353 CALL EAX

int j = q->doIt(3);
00401389 MOV DWORD PTR SS:[ESP+8],14 ;壓入默認參數20
00401391 MOV DWORD PTR SS:[ESP+4],3 ;壓入調用參數3
00401399 MOV EAX,DWORD PTR SS:[EBP-10]
0040139C MOV DWORD PTR SS:[ESP],EAX
0040139F MOV EAX,DWORD PTR DS:[EDX]
004013A1 CALL EAX

注意到兩個默認參數是在編譯時就已經寫死了,也就是說編譯器在編譯器就為兩個doIt調用分別決議了默認參數,然而在運行期它們卻是通過動態的方式
Call EAX
來運行,實際上在調試中也可以看到它們調用的都是子類的doIt函數(調用地址是相同的)。

我個人的理解是,虛函數的調用是通過虛函數表來完成的,故父類指針可以調用子類的函數,然而默認參數作為對象內存模型的一部分,是分別屬于不同的對象的,故編譯器為父類指針的函數調用還是賦予了父類對象的參數值。

請高手們指教  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-11-14 00:45 march rabbit
贊~  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-11-15 22:11 愛上龍卷風
@foobar
非常感謝foobar對本文詳盡的解釋。  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-11-15 23:00 foobar
@愛上龍卷風

不要感謝foobar,還是感謝google和c++編程思想吧。。。  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-11-16 12:30 pzy
@romangol

哈哈~我不太懂匯編,但應該明白你的意思了:lovedday的例子中,PARENT指針和CHILD指針調用的都是CHILD::doIt(),只不過在調用之前(編譯階段),編譯器已經它們填上默認參數值了,分別是10和20。

也就是說虛函數調用有多態性,而默認參數是靜態的,不存在運行時決策(如你所說,默認參數是在編譯時就已經寫死了)。

這個例子是有意設計成讓PARANT::doIt()與CHILD::doIt()的函數體相同,才有迷惑人的效果。

PS. 由此我進一步理解了C#為什么不支持默認參數值,也不鼓勵在庫中使用公開常量。默認參數值與常量都是在編譯后就“死”的,這個事實的后果是,修改庫后,用戶代碼需要重編譯。  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2007-12-27 22:06 秦歌
頂一下!  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2008-01-07 22:42 abettor.org
大家分析的都很好,學習了!  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2008-07-03 14:12 md6600
C++代碼本來就很明了精簡。 只不過 人比較懶惰,所以越來越簡。就會這樣咯。 寫句注釋嘛 有多難呢111  回復  更多評論
  

# What a joy to find such clear thinikng. Thanks for posting! 2011-05-26 10:20 Mateen
What a joy to find such clear thinikng. Thanks for posting!  回復  更多評論
  

# re: c++晦澀語法背后的故事(一) 2013-02-27 11:10 bluemei
用重寫來彌補一下:
class Base
{
public:
virtual void f(){
TRACE("Base f()\n");
}
virtual void f(int i){
TRACE("Base f(int)\n");
}
};
class Child : public Base
{
public:
virtual void f(){
TRACE("Child f()\n");
}
virtual void f(int i){
__super::f(i);
}
};

Child *p=new Child();
p->f();
p->f(10);  回復  更多評論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产精品福利在线观看网址| 亚洲女女女同性video| 亚洲国产精品悠悠久久琪琪| 在线播放精品| 亚洲欧洲三级电影| 一本一本久久a久久精品综合麻豆| 亚洲精选久久| 亚洲砖区区免费| 久久久久国产一区二区| 免费在线成人| 日韩亚洲欧美一区| 欧美一区二区三区啪啪| 欧美91大片| 国产精品天天看| 亚洲国产高清一区| 亚洲一区二区三区在线观看视频| 欧美一区观看| 亚洲国产一区二区在线| 亚洲视频一区在线观看| 欧美专区日韩专区| 欧美噜噜久久久xxx| 国产亚洲欧美色| 亚洲精品乱码久久久久久蜜桃麻豆| 亚洲一区国产一区| 欧美a级片网| 亚洲欧美国产精品va在线观看| 国内精品久久久| 美女精品在线观看| 国产精品一区二区欧美| 亚洲国产一区二区精品专区| 亚洲欧美日韩精品久久久| 玖玖玖国产精品| 亚洲午夜av电影| 欧美激情在线狂野欧美精品| 国产亚洲在线| 午夜精品久久久久久99热软件| 欧美成人午夜77777| 欧美一级在线视频| 国产精品福利av| 999亚洲国产精| 欧美va天堂| 欧美在线一级va免费观看| 欧美特黄一级大片| 日韩小视频在线观看专区| 免费观看日韩av| 欧美一区二区三区电影在线观看| 欧美三日本三级少妇三2023| 最新高清无码专区| 你懂的一区二区| 久久精品国产一区二区电影| 国产精品久久久久av免费| 一本色道**综合亚洲精品蜜桃冫| 欧美成人69| 免费不卡在线观看| 亚洲国产日韩在线| 欧美jizzhd精品欧美巨大免费| 欧美一进一出视频| 国产欧美一区二区视频| 午夜久久电影网| 亚洲制服av| 国产女主播一区| 久久成人免费网| 欧美一区成人| 韩国一区电影| 久久久青草婷婷精品综合日韩| 欧美在线免费看| 狠狠综合久久av一区二区老牛| 久久精品一本| 久久久人成影片一区二区三区观看 | 蜜桃精品一区二区三区| 狠狠色综合色区| 欧美高清视频在线| 欧美激情四色| 亚洲欧美日韩精品| 久久国产精品久久久久久久久久 | 亚洲国产精品久久久| 欧美激情网友自拍| 欧美日韩第一区日日骚| 亚洲欧美日韩综合国产aⅴ| 亚洲欧美中文日韩在线| 欧美在线视频一区| 欧美成人激情视频免费观看| 99re热精品| 亚洲天堂成人在线观看| 国产亚洲一区二区在线观看| 欧美成人一区二区在线| 欧美日韩裸体免费视频| 久久精品91| 欧美国产专区| 久久国产精品99久久久久久老狼| 久久久五月婷婷| 亚洲综合欧美| 老色批av在线精品| 亚洲一级在线| 久久夜色精品国产欧美乱| 一本色道久久综合亚洲91| 欧美一区二区在线免费播放| aa日韩免费精品视频一| 久久成人精品视频| 一区二区三区欧美日韩| 久久精品一区二区三区四区 | 欧美一区二区日韩一区二区| 久久免费视频网站| 亚洲欧美在线免费观看| 蜜桃久久精品一区二区| 欧美一区二区三区日韩| 欧美激情一区二区三区蜜桃视频| 久久不见久久见免费视频1| 免费欧美日韩| 久久青草福利网站| 欧美日韩中文在线观看| 免费看黄裸体一级大秀欧美| 国产精品私人影院| 亚洲日本中文字幕区| 狠狠狠色丁香婷婷综合激情| 亚洲网站视频福利| 亚洲免费成人av电影| 久久久久久亚洲精品中文字幕 | 久久精品国产v日韩v亚洲 | 欧美亚日韩国产aⅴ精品中极品| 欧美aa在线视频| 国产在线麻豆精品观看| 亚洲自拍另类| 午夜精品久久久久| 欧美精品自拍| 亚洲免费观看在线观看| 亚洲欧洲精品一区二区| 美女国产一区| 毛片一区二区| 在线播放日韩欧美| 久久婷婷丁香| 免费中文字幕日韩欧美| 在线欧美影院| 男男成人高潮片免费网站| 欧美福利电影在线观看| 亚洲欧洲三级电影| 欧美成人四级电影| 亚洲欧洲日韩在线| 在线亚洲欧美专区二区| 欧美在线亚洲综合一区| 国产精品日韩欧美综合| 亚洲免费视频中文字幕| 午夜精品久久久久久久| 国产精品一香蕉国产线看观看| 亚洲伊人一本大道中文字幕| 性色av一区二区三区在线观看| 国产精品一区免费视频| 久久av免费一区| 欧美电影在线观看| 日韩亚洲欧美一区二区三区| 欧美高清视频一二三区| 亚洲九九精品| 欧美一区二区视频观看视频| 国内在线观看一区二区三区| 久久综合电影一区| 亚洲每日在线| 久久久噜噜噜久久| 91久久精品国产| 国产精品久久久久久久久婷婷| 欧美一区二区三区婷婷月色| 欧美大片在线观看一区| 亚洲一区二区黄色| 黑人巨大精品欧美一区二区| 免费在线观看一区二区| 亚洲午夜伦理| 美女久久一区| 亚洲天堂成人在线视频| 国产综合网站| 欧美日韩一区二区三区在线| 欧美一区二区在线观看| 亚洲日本久久| 久久影院午夜论| 亚洲制服av| 亚洲黄色小视频| 国产午夜久久| 欧美先锋影音| 欧美国产日本韩| 久久岛国电影| 亚洲一级一区| 最新69国产成人精品视频免费| 欧美亚洲网站| 亚洲无玛一区| 亚洲日本aⅴ片在线观看香蕉| 国产欧美精品xxxx另类| 欧美日韩国产一中文字不卡 | 欧美涩涩视频| 久久这里只有精品视频首页| 亚洲专区在线| 夜夜嗨一区二区三区| 欧美+日本+国产+在线a∨观看| 午夜日韩av| 亚洲午夜免费福利视频| 91久久极品少妇xxxxⅹ软件| 国产主播一区| 国产人成一区二区三区影院| 欧美精品一区三区在线观看| 久久色中文字幕| 欧美中日韩免费视频| 亚洲综合国产| 亚洲夜间福利|