亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

C++中建立對象間消息連接的系統方法

2019-11-17 05:01:24
字體:
來源:轉載
供稿:網友
  用過C++進行過面向對象程序設計的用戶都知道,程序中的對象很少單獨存在。不考慮對象間的相互作用幾乎是不可能的。所以,標識對象間的關系或建立對象間的消息連接是面向對象程序設計的一項重要任務。    
    本文著重從C++程序設計的角度,提出一種建立對象間消息連接的實用方法。假如你想具體了解面向對象程序設計技術,請參閱有關專著?! ?大家都知道對象是數據和方法的封裝體。在C++中,它們分別表現為數據成員和成員函數。程序設計者通過執行對象的各種方法,來改變對象的狀態(即改變對象的屬性數據)。從而使該對象發生某些“事件”。當一對象發生某事件時,它通常需向其它相關對象發送“消息”,請求它們作出一些處理。 這時,發生事件并向其它對象請求處理的對象被稱為“事件對象”,而處理事件的對象被稱為“回調對象”。回調對象對事件的處理稱為“回調函數”?! ?在C++中,這一過程相當于:當事件對象發生事件時,調用回調對象的某些成員函數。通常的作法是回調對象向事件對象傳遞對象指針。但這種方法不通用。為了減少程序設計的工作量,本文提出一種建立對象間消息連接的系統方法。它的思路是:將“事件發生→請求處理→執行處理”這一過程抽象成一個“回調”(CallBack)類。通過繼續,用戶可以輕松獲取建立對象間消息連接的機制。    一、回調類的數據結構及其成員函數    本文提出的CallBack類支持三種回調函數。它們是:回調對象中的成員函數,屬于回調類的靜態成員函數和普通的C函數。CallBackle類中包含一回調函數表callBackList。它用于記錄事件名稱,指向回調函數及回調對象的指針。該表的每一個節點為一個事件記錄EventRecord。每個事件記錄包含三個域:事件名指針eventName,指向回調對象的指針pointerToCBO,指向回調函數的指針pointerToCBF或pointerToCBSF(其中,pointerToCBF指向回調對象的成員函數,pointerToCBSF指向回調類的靜態成員函數或普通函數。它們同處于一共用體內)。CallBack類所提供的回調機制是這樣的:在事件對象上注冊回調對象中的回調函數;當事件發生時,事件對象在其回調表中檢索并執行回調函數。從而使二者的消息連接得以建立。(關于該類的具體實現,請參閱文后所附的程序清單) 回調對象  事件對象   事件名 回調對象指針 回調函數指針“event” pointerCBO pointerToCBF或pointerTOCBSF- - - - - -
   AddCallBack: 注冊事件名和指向回調函數,回調對象的指針   CallCallBack: 在回調表中,檢索注冊在指定事件上回調函數并調用它們   事件發生時,調用CallCallBack函數   對事件event進行處理的成員函數   從CallBack類繼續的回調表callBackList, 成員函數AddCallBack和CallCallBack。   當回調函數為靜態成員函數或普通C函數時, pointerToCBO為NULL?! ?事件名是回調表callBackLis中的檢索要害字?! 』卣{對象中其它成員函數   CallBack類的成員函數AddCallBack用來將回調函數注冊到事件對象的回調表中。它有兩個重載版本:void CallBack::AddCallBack(char *event,CallBackFunction cbf,CallBack *p);
void CallBack::AddCallBack(char *event,CallBackStaticFunction cbsf);
   其中,第一個AddCallBack用來將某回調對象的成員函數注冊到事件對象的回調表中。第二個AddCallBack用來將或某回調類的靜態成員函數注冊到事件對象的回調表中。在上參數表中,event是指向事件名字符串的指針,p是指向回調對象的指針,cbf和cbsf分別是指向成員函數及靜態成員函數(或普通函數)的指針。當回調函數來自某回調對象SomeObject時,傳遞成員函數指針應采用如下格式:(CallBackFunction)&SomeObject::MemberFunctionName; 傳遞SomeObject類的某靜態成員函數指針應采用格式:
(CallBackStaticFunction)& SomeObject::FunctionName;傳遞程序中普通函數指針時,只需傳遞函數名即可。
   CallBack類的成員函數void CallBack::CallCallBack(char *ename, CallData calldata = NULL)用來調用注冊在事件ename上的所有回調函數。其中,calldata為數據指針(CallData實際上就是void*,詳見程序清單)。事件對象可通過它向回調對象傳遞有用的數據。該成員函數通常在事件對象的成員函數中調用,因為通常只有事件對象的成員函數才能改變對象的內部數據,從而使某些事件發生?! ?成員函數RemoveCallback用來刪除注冊在事件對象上的回調函數。它的三個重載版本依次為:void CallBack::RemoveCallBack(char *event,CallBackFunction cbf,CallBack *p);void CallBack::RemoveCallBack(char *event,CallBackStaticFunction cbsf);void CallBack::RemoveCallBack(char *event);
   其中,event,cbf,cbsf,p等參數和成員函數AddCallBack中各參數一樣。第一個RemoveCallBack用于刪除注冊在事件event上某回調對象的一個成員函數。第二個RemoveCallBack用于刪除注冊在事件event上的某普通函數或某回調類的一個靜態成員函數。第三個RemoveCallBack用于刪除注冊在事件event上的全部回調函數?! 《?、CallBack類的使用方法    使用CallBack類,可按以下步驟進行:   1.確定程序中哪些對象間存在關系,需要建立消息連接。并確定在各特定消息連接關系中,哪個對象是事件對象,哪個對象是回調對象?! ?2.事件對象類和回調對象類都必須從CallBack類繼續,以獲得回調支持?! ?3.為事件對象注冊回調數據。包括:事件名,回調函數名,指向回調對象的指針?! ?4.當你感愛好的事件發生時,在事件對象類引發事件的成員函數中調用CallCallBack函數?! ?下面是一個具體的例子。通過它你會對Callback類的使用方法有進一步的了解。file://測試程序文件:test.cpp #include"callback.h"file://“揚聲器”類 class Speaker:public CallBack

{
  PRivate:
   int volume;
  public:
   Speaker(int v): volume(v) {}
   void IncreaseVolume(int v) file://增加音量成員函數
   {
    volume += v;
    if(volume >20){ file://“音量大于20”事件發生了
     file://調用注冊在兩事件上的回調函數
     CallCallBack("音量改變了");
     CallCallBack("音量大于20", &volume);
    }
   }  void DecreaseVolume(int v) file://降低音量成員函數
  {
   volume -= v;
   if(volume < 5){ file://“音量小于5”事件發生了
    file://調用注冊在兩事件上的回調函數
    CallCallBack("音量改變了");
    CallCallBack("音量小于5", &volume);
   }
  }
};file://“耳朵”類 class Ear : public CallBack
{
  public:
   static void Response(CallData callData) file://對“音量改變”的反應
   {
    cout<<"音量改變了."<   }
   void HighVoiceResponse(CallData callData)//對高音的反應
   {
    cout<<”喂!太吵了!現在音量是:"<<*((int *)callData)<   }
   void LowVoiceResponse(CallData callData)// 對低音的反應
   {
    cout<<"??!我聽不清了?,F在音量是:"<<*((int *)callData)<   }
};void main(void)
{
  Speaker s(10); file://現在音量為10
  Ear e;
  file://為事件對象s注冊回調函數
  s.AddCallBack("音量大于20”,(CallBackFunction)&Ear::HighVoiceResponse,&e);
  s.AddCallBack("音量小于5”,(CallBackFunction)&Ear::LowVoiceResponse,&e);
  s.AddCallBack("音量改變了",(CallBackStaticFunction)&Ear::Response);
  s.IncreaseVolume(12);//將音量增加12,現在音量位22
  s.DecreaseVolume(20);//將音量減少20,現在音量位2
}
   運行結果:    音量改變了.   喂!太吵了!現在音量是:22   音量改變了.   ??!我聽不清了?,F在音量是:2   在上例中,揚聲器對象s為事件對象,耳朵對象e為回調對象。。s上被注冊了三個事件:“音量改變了”,“音量大于20”,“音量小于5”。 回調函數分別為:Ear::Response, Ear::HighVoiceResponse,Ear::LowVoiceResponse。當揚聲器s通過其成員函數IncreaseVolume和 DecreaseVolume改變音量時,回調對象e會自動作出反應。可見,通過使用CallBack類,在對象間建立消息連接已變為一項很簡單和美麗的工作。   由于筆者水平有限,該類的設計必有不完善之處。假如您對它感愛好,筆者可與各位C++玩家共同探討這類問題?! ?聯系方式:fei_xiang@263.net
 更多內容請看C/C++技術專題  C/C++進階技術文檔  系統安全設置專題,或   附:程序清單(本程序在MS VC++5.0和TC++3.0上均編譯通過)file://回調類的類結構:callback.h#ifndef _CALLBACK_H#define _CALLBACK_H#include<stdlib.h>#include<string.h>#include<iostream.h>#define CALLBACKLIST_INIT_SIZE 10#define CALLBACKLIST_INCREMENT 5class CallBack;typedef void *CallData;//回調數據指針類型定義typedef void (CallBack::*CallBackFunction)(CallData); file://指向回調成員函數的指針typedef void (*CallBackStaticFunction)(CallData); file://指向靜態成員函數或普通函數的指針類型定義class EventRecord{
  private:
   char *eventName; file://回調事件名稱
   CallBack *pointerToCBO;//指向回調對象的指針
   file://指向成員函數的指針和指向靜態成員函數(或普通函數)指針的共用體
   union{
    CallBackFunction pointerToCBF;
    CallBackStaticFunction pointerToCBSF;
   };
  public:
   EventRecord(void); file://事件記錄類的缺省構造函數
   file://構造包含成員函數的事件記錄
   EventRecord(char *ename,CallBack *pCBO,CallBackFunction pCBF);

   file://構造包含靜態成員函數或普通函數的事件記錄
   EventRecord(char *ename,CallBackStaticFunction pCBSF);
   ~EventRecord(void);//析構事件記錄
   void Operator = (const EventRecord& er);//重載賦值運算符
   file://判定當前事件記錄的事件名是否為ename   int operator == (char *ename) const;   file://判定當前事件記錄是否和指定事件記錄相等   int operator == (const EventRecord& er) const;   void Flush(void); file://將當前事件記錄清空   int IsEmpty(void) const;//判定事件記錄是否為空(即事件名是否為空)   friend class CallBack; file://讓CallBack類能訪問EventRecord的私有成員;};class CallBack {
  private:
   EventRecord *callBackList; file://回調事件表
   int curpos; file://當前事件記錄位置
   int lastpos; file://回調表中最后一空閑位置
   int size; file://回調表的大小   void MoveFirst(void) { curpos = 0; }//將當前記錄置為第一條記錄
   void MoveNext(void) file://將下一條記錄置為當前記錄
   {
    if(curpos == lastpos) return;
    curpos++;
   }   file://判定回調表是否被遍歷完    int EndOfList(void) const { return curpos == lastpos; }
    public:
     CallBack(void);//構造函數
     CallBack(const CallBack& cb);//拷貝構造函數
     ~CallBack(void);//析構函數   void operator = (const CallBack& cb);// 重載賦值運算符   file://將回調對象的成員函數、靜態成員函數(或普通函數) file://注冊為事件對象的回調函數   void AddCallBack(char *event,CallBackFunction cbf,CallBack *p);
   void AddCallBack(char *event,CallBackStaticFunction cbsf);
   file://刪除注冊在指定事件上的回調函數   void RemoveCallBack(char *event,CallBackFunction cbf,CallBack *p);
   void RemoveCallBack(char *event,CallBackStaticFunction cbsf);
   void RemoveCallBack(char *event);// 刪除某事件的全部記錄   file://執行注冊在某一事件上的所有回調函數   void CallCallBack(char *event, CallData calldata = NULL);  };  #endif  file://回調類的實現:callback.cpp   #include"callback.h"  file://EventRecord類的實現  EventRecord::EventRecord(void)
  {
   eventName = NULL;
   pointerToCBO = NULL;
   file://因為sizeof(CallBackFunction) > sizeof(CallBackStaticFunction)
   pointerToCBF = NULL;
  }  EventRecord::EventRecord(char *ename, CallBack *pCBO, CallBackFunction pCBF)
  :pointerToCBO(pCBO), pointerToCBF(pCBF)
  {
   eventName = strdup(ename);
  }  EventRecord::EventRecord(char *ename, CallBackStaticFunction pCBSF)
  :pointerToCBO(NULL), pointerToCBSF(pCBSF)
  {
   eventName = strdup(ename);
  }  EventRecord::~EventRecord(void)
  {
   if(eventName) delete eventName;
  }  void EventRecord::operator = (const EventRecord& er)
  {
   if(er.eventName)
    eventName = strdup(er.eventName);
   else
    eventName = NULL;
    pointerToCBO = er.pointerToCBO;
    pointerToCBF = er.pointerToCBF;
  }  int EventRecord::operator == (char *ename) const
  {
   if((eventName == NULL)ename == NULL)
    return eventName == ename;
   else
    return strcmp(eventName,ename) == 0;

  }  int EventRecord::operator == (const EventRecord& er) const
  {
   return (er == eventName) /*er和eventname不能交換位置*/
     &&(pointerToCBO == er.pointerToCBO)
     &&(pointerToCBO ?
     (pointerToCBF == er.pointerToCBF):
     (pointerToCBSF == er.pointerToCBSF));
  }  void EventRecord::Flush(void)
  {
   if(eventName){
    delete eventName;
    eventName = NULL;
   }
   pointerToCBO = NULL;
   pointerToCBF = NULL;
  }  int EventRecord::IsEmpty(void) const
  {
   if(eventName == NULL)
    return 1;
   else
    return 0;
  }  file://Callback類的實現
  CallBack::CallBack(void)
  {
   file://按初始尺寸為回調表分配內存空間   callBackList = new EventRecord[CALLBACKLIST_INIT_SIZE];   if(!callBackList){
    cerr<<"CallBack: memory allocation error."<<endl;
    exit(1);
   }
   size = CALLBACKLIST_INIT_SIZE;
   lastpos = 0;
   curpos = 0;
  }  CallBack::CallBack(const CallBack& cb): curpos(cb.curpos),lastpos(cb.lastpos),size(cb.size)
  {
   callBackList = new EventRecord[size];
   if(!callBackList){
    cerr<<"CallBack: memory allocation error."<<endl;
    exit(1);
   }
   file://一一復制各條事件記錄
   for(int i = 0; i < size; i++) callBackList[i] = cb.callBackList[i];
  }  void CallBack::operator = (const CallBack& cb)
  {
   curpos = cb.curpos;
   lastpos = cb.lastpos;
   size = cb.size;
   delete [] callBackList;//刪除舊的回調表
   callBackList = new EventRecord[size];//重新分配內存空間
   if(!callBackList){
    cerr<<"CallBack: memory allocation error."<<endl;
    exit(1);
   }   file://一一復制各條事件記錄   for(int i = 0; i < size; i++) callBackList[i] = cb.callBackList[i];
  }  CallBack::~CallBack(void)
  {
   delete [] callBackList;
  }  void CallBack::AddCallBack(char *event, CallBackFunction pCBF, CallBack *pCBO)
  {
   file://如事件名為空,退出
   if( (event == NULL)?1:(strlen(event) == 0)) return;
   file://尋找因刪除事件記錄而產生的第一個空閑位置,并填寫新事件記錄
   for(int start=0;start<lastpos;start++)
    if(callBackList[start].IsEmpty()){
     callBackList[start] = EventRecord(event,pCBO,pCBF);
     break;
    }
    if(start < lastpos) return; file://確實存在空閑位置
    file://沒有空閑位置,在回調表后追加新記錄
    if(lastpos == size) file://回調表已滿,需“伸長”
    {
     EventRecord *tempList = callBackList;//暫存舊回調表指針
     file://以一定的步長“伸長”回調表
     callBackList = new EventRecord[size + CALLBACKLIST_INCREMENT];
     if(!callBackList){
      cerr<<"CallBack: memory allocation error."<<endl;
      exit(1);
     }
     file://復制舊回調表中的記錄
     for(int i = 0; i < size; i++) callBackList[i] = tempList[i];
     delete [] tempList;//刪除舊回調表
     size += CALLBACKLIST_INCREMENT;//記下新回調表的尺寸
    }
    file://構造新的事件記錄并將其填入回調表中

    callBackList[lastpos] = EventRecord(event,pCBO,pCBF);
    lastpos++;
   }
   void CallBack::AddCallBack(char *event,CallBackStaticFunction pCBSF)
   {
    if( (event == NULL)?1:(strlen(event) == 0)) return;
    for(int start=0;start<lastpos;start++)
     if(callBackList[start].IsEmpty()){
      callBackList[start] = EventRecord(event,pCBSF);
      break;
     }
    if(start < lastpos) return; file://a hole is found
    if(lastpos == size) file://event list is insufficient
    {
     EventRecord *tempList = callBackList;
     callBackList = new EventRecord[size + CALLBACKLIST_INCREMENT];     if(!callBackList){
      cerr<<"CallBack: memory allocation error."<<endl;
      exit(1);
     }
     for(int i = 0; i < size; i++) callBackList[i] = tempList[i];
     delete [] tempList;
     size += CALLBACKLIST_INCREMENT;
    }   callBackList[lastpos] = EventRecord(event,pCBSF);
   lastpos++;
  }   file://刪除注冊在指定事件上的成員函數  void CallBack::RemoveCallBack(char *event, CallBackFunction pCBF, CallBack *pCBO)
  {
   if( (event == NULL)?1:(strlen(event) == 0)) return;
   EventRecord er(event,pCBO,pCBF);   for(int i = 0; i < lastpos; i++)
    if(callBackList[i] == er) callBackList[i].Flush();
  }  file://刪除注冊在指定事件上的靜態成員函數或普通函數  void CallBack::RemoveCallBack(char *event,CallBackStaticFunction pCBSF)
  {
   if( (event == NULL)?1:(strlen(event) == 0)) return;
   EventRecord er(event,pCBSF);   for(int i = 0; i < lastpos; i++)
    if(callBackList[i] == er) callBackList[i].Flush();
  }  file://刪除注冊在指定事件上的所有回調函數  void CallBack::RemoveCallBack(char *event)
  {
   if( (event == NULL)?1:(strlen(event) == 0)) return;
   for(int i = 0; i < lastpos; i++)
    if(callBackList[i] == event) callBackList[i].Flush();
  }  void CallBack::CallCallBack(char *event, CallData callData)
  {
   if( (event == NULL)?1:(strlen(event) == 0)) return;
   CallBack *pCBO;
   CallBackFunction pCBF;
   CallBackStaticFunction pCBSF;
   MoveFirst();
   while(!EndOfList())
   {
    file://如當前事件記錄和指定事件不匹配,轉入下一條記錄繼續循環
    if(!(callBackList[curpos] == event))
    {
     MoveNext();
     continue;
    }
    file://如找到匹配記錄
    pCBO = callBackList[curpos].pointerToCBO;
    file://如事件記錄中回調對象指針為空,說明該記錄中保存的是靜態函數指針
    if(pCBO == NULL){
     pCBSF = callBackList[curpos].pointerToCBSF;
     pCBSF(callData);//調用該靜態回調函數
    }
    else file://如事件記錄中回調對象指針非空,說明該記錄中保存的是成員函數指針
    {
     pCBF = callBackList[curpos].pointerToCBF;
     (pCBO->*pCBF)(callData);// 調用該回調對象的成員函數
    }
    MoveNext();
   }
  }  更多內容請看C/C++技術專題  C/C++進階技術文檔  系統安全設置專題,


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久亚洲精选| 欧美性高潮床叫视频| 中文字幕日韩av电影| 欧美最猛性xxxxx(亚洲精品)| 久久中文字幕一区| 亚洲欧洲日产国码av系列天堂| 亚洲精品小视频| 人人澡人人澡人人看欧美| 日本久久久久亚洲中字幕| 亚洲国产精品999| 日本亚洲欧洲色α| 欧美一区深夜视频| 欧美精品电影在线| 成人情趣片在线观看免费| 日本免费久久高清视频| 国产69精品久久久| 国产精品www| 日本精品一区二区三区在线| 国产偷亚洲偷欧美偷精品| 国产成人精品av| 久久久最新网址| 欧美中文字幕在线观看| 精品亚洲国产成av人片传媒| 国产精品成人一区二区三区吃奶| 国产精品视频午夜| 成人黄色中文字幕| 久久久精品免费| 欧美黑人xxx| 国产精品一区二区三区毛片淫片| 久久免费在线观看| 久久亚洲欧美日韩精品专区| 一本色道久久88综合日韩精品| 亚洲第一精品夜夜躁人人躁| 4438全国亚洲精品在线观看视频| 国产精品视频男人的天堂| 久久这里有精品| 久久精品国产综合| 中文字幕亚洲无线码a| 欧美日韩视频在线| 亚洲欧美日韩高清| 亚洲第一天堂无码专区| 亚洲天堂av电影| 欧美片一区二区三区| 一区二区亚洲欧洲国产日韩| 国产在线观看精品一区二区三区| 国产精品久久久久久久久男| 欧美激情手机在线视频| 国产精品av网站| 亚洲图片欧美午夜| 久久久人成影片一区二区三区| 国产亚洲精品一区二区| 亚洲热线99精品视频| 亚洲美女精品成人在线视频| 亚洲一区制服诱惑| 国产成人久久精品| 2019亚洲日韩新视频| 欧美激情精品久久久久久黑人| 欧美激情亚洲另类| 午夜免费日韩视频| 97av视频在线| 色妞色视频一区二区三区四区| 国产亚洲精品91在线| 综合网中文字幕| 中文字幕日韩av综合精品| 国产视频久久久久| 亚洲一区二区三区毛片| 一区二区日韩精品| 91精品国产成人| 欧美午夜视频在线观看| 国外色69视频在线观看| 日韩hd视频在线观看| 欧美激情一区二区三区久久久| 欧美在线视频导航| 亚洲一区二区三| 色yeye香蕉凹凸一区二区av| 日本中文字幕久久看| 亚洲欧美日韩久久久久久| 国产91av在线| 91久久综合亚洲鲁鲁五月天| 成人福利网站在线观看| 成人国产亚洲精品a区天堂华泰| 国产日韩综合一区二区性色av| 欧美第一淫aaasss性| 91亚洲精华国产精华| 91九色视频在线| 国产精品一区久久久| 欧美www在线| 成人免费自拍视频| 亚洲欧美在线免费观看| 亚洲欧美福利视频| 欧美午夜精品久久久久久久| 国产精品igao视频| 91国内免费在线视频| 国产成人av在线播放| 久久亚洲电影天堂| 色综合久久天天综线观看| 久久成人这里只有精品| 欧美国产日本高清在线| 色999日韩欧美国产| 久久综合伊人77777尤物| 成人在线免费观看视视频| 国产a级全部精品| 亚洲字幕一区二区| 日韩女优在线播放| 色综合久久88色综合天天看泰| 日韩经典一区二区三区| 日本老师69xxx| 日韩视频第一页| 国产视频精品va久久久久久| 亚洲乱码国产乱码精品精天堂| 国产亚洲精品综合一区91| 夜夜嗨av色综合久久久综合网| 国产日产欧美精品| 日本成人在线视频网址| 一本一道久久a久久精品逆3p| 亚洲第一网站免费视频| 欧美xxxx18国产| 日韩美女主播视频| 九九热这里只有在线精品视| 国产成人欧美在线观看| 日韩黄色av网站| 日韩中文综合网| 亚洲精品第一国产综合精品| 亚洲三级黄色在线观看| 亚洲精品久久久久久久久久久久久| 久久久国产精品视频| 国产精品久久久久久久久久| 性色av一区二区三区红粉影视| 日韩精品免费综合视频在线播放| 国产一区二中文字幕在线看| 久久久久久亚洲精品中文字幕| 亚洲男女自偷自拍图片另类| 菠萝蜜影院一区二区免费| 中日韩美女免费视频网站在线观看| 亚洲黄页视频免费观看| 国产成+人+综合+亚洲欧美丁香花| 中文字幕在线精品| 日韩精品免费看| 欧美成人免费小视频| 国产精品久久久久久婷婷天堂| 国产精品都在这里| 久久精品成人欧美大片| 欧美福利在线观看| 色综合久久88色综合天天看泰| 欧美大片大片在线播放| 欧美日韩一区二区三区在线免费观看| 亚洲第一视频在线观看| 久久成人18免费网站| 国产精品久久久久久久久免费看| 亚洲精品免费一区二区三区| 91久久久亚洲精品| 8x海外华人永久免费日韩内陆视频| 午夜精品久久久久久久男人的天堂| 精品亚洲va在线va天堂资源站| 国产精品视频午夜| 亚洲精品成人av| 日韩在线精品一区| 日韩黄色av网站| 亚洲欧美日韩爽爽影院| 精品无人区太爽高潮在线播放| 日韩中文字幕网| 国产精品九九九| 亚洲福利精品在线| 久久久免费观看视频|