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

首頁 > 編程 > C# > 正文

C#中Override關鍵字和New關鍵字的用法詳解

2020-01-24 01:18:44
字體:
來源:轉載
供稿:網友

C# 語言經過專門設計,以便不同庫中的基類與派生類之間的版本控制可以不斷向前發展,同時保持向后兼容。這具有多方面的意義。例如,這意味著在基類中引入與派生類中的某個成員具有相同名稱的新成員在 C# 中是完全支持的,不會導致意外行為。它還意味著類必須顯式聲明某方法是要重寫一個繼承方法,還是一個隱藏具有類似名稱的繼承方法的新方法。
在 C# 中,派生類可以包含與基類方法同名的方法。
基類方法必須定義為 virtual。

  • 如果派生類中的方法前面沒有 new 或 override 關鍵字,則編譯器將發出警告,該方法將有如存在 new 關鍵字一樣執行操作。
  • 如果派生類中的方法前面帶有 new 關鍵字,則該方法被定義為獨立于基類中的方法。
  • 如果派生類中的方法前面帶有 override 關鍵字,則派生類的對象將調用該方法,而不是調用基類方法。

可以從派生類中使用 base 關鍵字調用基類方法。

override、virtual 和 new 關鍵字還可以用于屬性、索引器和事件中。
默認情況下,C# 方法為非虛方法。如果某個方法被聲明為虛方法,則繼承該方法的任何類都可以實現它自己的版本。若要使方法成為虛方法,必須在基類的方法聲明中使用 virtual 修飾符。然后,派生類可以使用 override 關鍵字重寫基虛方法,或使用 new 關鍵字隱藏基類中的虛方法。如果 override 關鍵字和 new 關鍵字均未指定,編譯器將發出警告,并且派生類中的方法將隱藏基類中的方法。
為了在實踐中演示上述情況,我們暫時假定公司 A 創建了一個名為 GraphicsClass 的類,您的程序將使用此類。 GraphicsClass 如下所示:

class GraphicsClass{  public virtual void DrawLine() { }  public virtual void DrawPoint() { }}

您的公司使用此類,并且您在添加新方法時將其用來派生自己的類:

class YourDerivedGraphicsClass : GraphicsClass{  public void DrawRectangle() { }}

您的應用程序運行正常,直到公司 A 發布了 GraphicsClass 的新版本,類似于下面的代碼:

class GraphicsClass{  public virtual void DrawLine() { }  public virtual void DrawPoint() { }  public virtual void DrawRectangle() { }}

現在,GraphicsClass 的新版本中包含一個名為 DrawRectangle 的方法。開始時,沒有出現任何問題。新版本仍然與舊版本保持二進制兼容。已經部署的任何軟件都將繼續正常工作,即使新類已安裝到這些軟件所在的計算機系統上。在您的派生類中,對方法 DrawRectangle 的任何現有調用將繼續引用您的版本。
但是,一旦您使用 GraphicsClass 的新版本重新編譯應用程序,就會收到來自編譯器的警告 CS0108。此警告提示您必須考慮希望 DrawRectangle 方法在應用程序中的工作方式。
如果您希望自己的方法重寫新的基類方法,請使用 override 關鍵字:

class YourDerivedGraphicsClass : GraphicsClass{  public override void DrawRectangle() { }}

override 關鍵字可確保派生自 YourDerivedGraphicsClass 的任何對象都將使用 DrawRectangle 的派生類版本。派生自 YourDerivedGraphicsClass 的對象仍可以使用基關鍵字訪問 DrawRectangle 的基類版本:

base.DrawRectangle();

如果您不希望自己的方法重寫新的基類方法,則需要注意以下事項。為了避免這兩個方法之間發生混淆,可以重命名您的方法。這可能很耗費時間且容易出錯,而且在某些情況下并不可行。但是,如果您的項目相對較小,則可以使用 Visual Studio 的重構選項來重命名方法。

或者,也可以通過在派生類定義中使用關鍵字 new 來防止出現該警告:

class YourDerivedGraphicsClass : GraphicsClass{  public new void DrawRectangle() { }}

使用 new 關鍵字可告訴編譯器您的定義將隱藏基類中包含的定義。這是默認行為。
重寫和方法選擇
當在類中指定方法時,如果有多個方法與調用兼容(例如,存在兩種同名的方法,并且其參數與傳遞的參數兼容),則 C# 編譯器將選擇最佳方法進行調用。下面的方法將是兼容的:

public class Derived : Base{  public override void DoWork(int param) { }  public void DoWork(double param) { }}

在 Derived 的一個實例中調用 DoWork 時,C# 編譯器將首先嘗試使該調用與最初在 Derived 上聲明的 DoWork 版本兼容。重寫方法不被視為是在類上進行聲明的,而是在基類上聲明的方法的新實現。僅當 C# 編譯器無法將方法調用與 Derived 上的原始方法匹配時,它才嘗試將該調用與具有相同名稱和兼容參數的重寫方法匹配。例如:

int val = 5;Derived d = new Derived();d.DoWork(val); // Calls DoWork(double).

由于變量 val 可以隱式轉換為 double 類型,因此 C# 編譯器將調用 DoWork(double),而不是 DoWork(int)。有兩種方法可以避免此情況。首先,避免將新方法聲明為與虛方法同名。其次,可以通過將 Derived 的實例強制轉換為 Base 來使 C# 編譯器搜索基類方法列表,從而使其調用虛方法。由于是虛方法,因此將調用 Derived 上的 DoWork(int) 的實現。例如:

((Base)d).DoWork(val); // Calls DoWork(int) on Derived.

何時使用 Override 和 New 關鍵字
在 C# 中,派生類中方法的名稱可與基類中方法的名稱相同。可通過使用 new 和 override 關鍵字指定方法互動的方式。 override 修飾符 extends 基類方法,且 new 修飾符將其“隱藏”起來。這種區別在本主題中的示例顯示出來。
在控制臺應用程序中,聲明下面的 BaseClass 和 DerivedClass 兩個類. DerivedClass 繼承自 BaseClass。

class BaseClass{  public void Method1()  {    Console.WriteLine("Base - Method1");  }}class DerivedClass : BaseClass{  public void Method2()  {    Console.WriteLine("Derived - Method2");  }}

在 Main 方法中,聲明變量 bc、dc 和 bcdc。

  • bc 的類型為 BaseClass,并且其值的類型為 BaseClass。
  • dc的類型為 DerivedClass,并且其值的類型為 DerivedClass。
  • bcdc的類型為 BaseClass,并且其值的類型為 DerivedClass。這是要密切注意的變量。

由于 bc 和 bcdc 具有類型 BaseClass,因此,除非您使用強制轉換,否則它們只會直接訪問 Method1。變量 dc 可以訪問 Method1 和 Method2。下面的代碼演示這些關系。

class Program{  static void Main(string[] args)  {    BaseClass bc = new BaseClass();    DerivedClass dc = new DerivedClass();    BaseClass bcdc = new DerivedClass();    bc.Method1();    dc.Method1();    dc.Method2();    bcdc.Method1();  }  // Output:  // Base - Method1  // Base - Method1  // Derived - Method2  // Base - Method1}

接下來,將以下 Method2 方法添加到 BaseClass。此方法的簽名與 DerivedClass 中 Method2 方法的簽名相匹配。

public void Method2(){  Console.WriteLine("Base - Method2");}

由于 BaseClass 現在有 Method2 方法,因此可以為 BaseClass 變量 bc 和 bcdc 添加第二個調用語句,如下面的代碼所示。

bc.Method1();bc.Method2();dc.Method1();dc.Method2();bcdc.Method1();bcdc.Method2();


當生成項目時,您將看到在 BaseClass 中添加 Method2 方法將引發警告。警告提示,DerivedClass 中的 Method2 方法將 Method2 方法隱藏在 BaseClass 中。如果要獲得該結果,則建議您使用 Method2 定義中的 new 關鍵字?;蛘撸梢灾孛?Method2 方法之一來解決警告,但這始終不實用。
在添加 new 之前,運行該程序以查看其他調用語句生成的輸出。顯示以下結果。

輸出:

Base - Method1Base - Method2Base - Method1Derived - Method2Base - Method1Base - Method2

new 關鍵字可以保留生成輸出的關系,但它將取消警告。具有 BaseClass 類型的變量繼續訪問 BaseClass 成員,具有 DerivedClass 類型的變量首先繼續訪問 DerivedClass 中的成員,然后再考慮從 BaseClass 繼承的成員.
要禁止顯示警告,請向 DerivedClass 中的 Method2 定義添加 new 修飾符,如下面的示例所示:可在 public 前后添加修飾符。

public new void Method2(){  Console.WriteLine("Derived - Method2");}

再次運行該程序以確認沒有更改輸出。還確認警告不再出現。通過使用 new,您斷言您了解它修改的成員將隱藏從基類繼承的成員。關于通過繼承隱藏名稱的更多信息,請參見 new 修飾符(C# 參考)。
要將此行為與使用 override 的效果進行對比,請將以下方法添加到 DerivedClass。可在 public 的前面或后面添加 override 修飾符。

public override void Method1(){  Console.WriteLine("Derived - Method1");}

將 virtual 修飾符添加到 BaseClass 中的 Method1 的定義。可在 public 的前面或后面添加 virtual 修飾符。

public virtual void Method1(){  Console.WriteLine("Base - Method1");}

再次運行項目。尤其請注意下面輸出的最后兩行。

輸出:

Base - Method1Base - Method2Derived - Method1Derived - Method2Derived - Method1Base - Method2

使用 override 修飾符使 bcdc 能夠訪問 DerivedClass 中定義的 Method1 方法。通常,這是繼承層次結構中所需的行為。讓具有從派生類創建的值的對象使用派生類中定義的方法。通過使用 override 擴展基類方法可實現該行為。
下面的代碼包括完整的示例。

using System;using System.Text;namespace OverrideAndNew{  class Program  {    static void Main(string[] args)    {      BaseClass bc = new BaseClass();      DerivedClass dc = new DerivedClass();      BaseClass bcdc = new DerivedClass();      // The following two calls do what you would expect. They call      // the methods that are defined in BaseClass.      bc.Method1();      bc.Method2();      // Output:      // Base - Method1      // Base - Method2      // The following two calls do what you would expect. They call      // the methods that are defined in DerivedClass.      dc.Method1();      dc.Method2();      // Output:      // Derived - Method1      // Derived - Method2      // The following two calls produce different results, depending       // on whether override (Method1) or new (Method2) is used.      bcdc.Method1();      bcdc.Method2();      // Output:      // Derived - Method1      // Base - Method2    }  }  class BaseClass  {    public virtual void Method1()    {      Console.WriteLine("Base - Method1");    }    public virtual void Method2()    {      Console.WriteLine("Base - Method2");    }  }  class DerivedClass : BaseClass  {    public override void Method1()    {      Console.WriteLine("Derived - Method1");    }    public new void Method2()    {      Console.WriteLine("Derived - Method2");    }  }}


以下示例顯示了不同上下文中的類似行為。該示例定義了三個類:一個名為 Car 的基類,和兩個由其派生的 ConvertibleCar 和 Minivan?;愔邪?DescribeCar 方法。該方法給出了對一輛車的基本描述,然后調用 ShowDetails 來提供其他的信息。這三個類中的每一個類都定義了 ShowDetails 方法。 new 修飾符用于定義 ConvertibleCar 類中的 ShowDetails。 override 修飾符用于定義 Minivan 類中的 ShowDetails。

// Define the base class, Car. The class defines two methods,// DescribeCar and ShowDetails. DescribeCar calls ShowDetails, and each derived// class also defines a ShowDetails method. The example tests which version of// ShowDetails is selected, the base class method or the derived class method.class Car{  public void DescribeCar()  {    System.Console.WriteLine("Four wheels and an engine.");    ShowDetails();  }  public virtual void ShowDetails()  {    System.Console.WriteLine("Standard transportation.");  }}// Define the derived classes.// Class ConvertibleCar uses the new modifier to acknowledge that ShowDetails// hides the base class method.class ConvertibleCar : Car{  public new void ShowDetails()  {    System.Console.WriteLine("A roof that opens up.");  }}// Class Minivan uses the override modifier to specify that ShowDetails// extends the base class method.class Minivan : Car{  public override void ShowDetails()  {    System.Console.WriteLine("Carries seven people.");  }}

該示例測試被調用的 ShowDetails 版本。以下方法,TestCars1 為每個類提供了一個實例,并在每個實例上調用 DescribeCar。

public static void TestCars1(){  System.Console.WriteLine("/nTestCars1");  System.Console.WriteLine("----------");  Car car1 = new Car();  car1.DescribeCar();  System.Console.WriteLine("----------");  // Notice the output from this test case. The new modifier is  // used in the definition of ShowDetails in the ConvertibleCar  // class.   ConvertibleCar car2 = new ConvertibleCar();  car2.DescribeCar();  System.Console.WriteLine("----------");  Minivan car3 = new Minivan();  car3.DescribeCar();  System.Console.WriteLine("----------");}


TestCars1 生成以下輸出:尤其請注意 car2 的結果,該結果可能不是您所需的內容。對象的類型是 ConvertibleCar,但 DescribeCar 不會訪問 ConvertibleCar 中定義的 ShowDetails 版本,因為方法已聲明包含 new 修飾符,而不是 override 修飾符。因此,ConvertibleCar 對象顯示與 Car 對象相同的說明。比較 car3 的結果,它是一個 Minivan 對象。在這種情況下,在 Minivan 類中聲明的 ShowDetails 方法重寫 Car 類中聲明的 ShowDetails 方法,顯示的說明描述微型面包車。

// TestCars1// ----------// Four wheels and an engine.// Standard transportation.// ----------// Four wheels and an engine.// Standard transportation.// ----------// Four wheels and an engine.// Carries seven people.// ----------

TestCars2 創建 Car 類型的對象列表。對象的值由 Car、ConvertibleCar 和 Minivan 類實例化而來。 DescribeCar 是調用列表中的每個元素。以下代碼顯示了 TestCars2 的定義。

public static void TestCars2(){  System.Console.WriteLine("/nTestCars2");  System.Console.WriteLine("----------");  var cars = new List<Car> { new Car(), new ConvertibleCar(),     new Minivan() };  foreach (var car in cars)  {    car.DescribeCar();    System.Console.WriteLine("----------");  }}

顯示以下輸出。請注意,此輸出與由 TestCars1 顯示的輸出相同。 ConvertibleCar 類的 ShowDetails 方法不被調用,無論對象的類型是 ConvertibleCar,如在 TestCars1 中,還是 Car,如在 TestCars2 中。相反,car3 在兩種情況下都從 Minivan 類調用 ShowDetails 方法,無論它具有類型 Minivan 還是類型 Car。

// TestCars2// ----------// Four wheels and an engine.// Standard transportation.// ----------// Four wheels and an engine.// Standard transportation.// ----------// Four wheels and an engine.// Carries seven people.// ----------

完成示例的方法 TestCars3 和 TestCars4。這些方法直接調用 ShowDetails,首先從宣布具有類型 ConvertibleCar 和 Minivan (TestCars3) 的對象調用,然后從具有類型 Car (TestCars4) 的對象調用。以下代碼定義了這兩種方法。

public static void TestCars3(){  System.Console.WriteLine("/nTestCars3");  System.Console.WriteLine("----------");  ConvertibleCar car2 = new ConvertibleCar();  Minivan car3 = new Minivan();  car2.ShowDetails();  car3.ShowDetails();}public static void TestCars4(){  System.Console.WriteLine("/nTestCars4");  System.Console.WriteLine("----------");  Car car2 = new ConvertibleCar();  Car car3 = new Minivan();  car2.ShowDetails();  car3.ShowDetails();}

該方法產生下面的輸出,它對應本主題中第一個示例的結果。

// TestCars3// ----------// A roof that opens up.// Carries seven people.// TestCars4// ----------// Standard transportation.// Carries seven people.

以下代碼顯示了整個項目及其輸出。

using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace OverrideAndNew2{  class Program  {    static void Main(string[] args)    {      // Declare objects of the derived classes and test which version      // of ShowDetails is run, base or derived.      TestCars1();      // Declare objects of the base class, instantiated with the      // derived classes, and repeat the tests.      TestCars2();      // Declare objects of the derived classes and call ShowDetails      // directly.      TestCars3();      // Declare objects of the base class, instantiated with the      // derived classes, and repeat the tests.      TestCars4();    }    public static void TestCars1()    {      System.Console.WriteLine("/nTestCars1");      System.Console.WriteLine("----------");      Car car1 = new Car();      car1.DescribeCar();      System.Console.WriteLine("----------");      // Notice the output from this test case. The new modifier is      // used in the definition of ShowDetails in the ConvertibleCar      // class.       ConvertibleCar car2 = new ConvertibleCar();      car2.DescribeCar();      System.Console.WriteLine("----------");      Minivan car3 = new Minivan();      car3.DescribeCar();      System.Console.WriteLine("----------");    }

輸出:

TestCars1----------Four wheels and an engine.Standard transportation.----------Four wheels and an engine.Standard transportation.----------Four wheels and an engine.Carries seven people.----------


 

    public static void TestCars2()    {      System.Console.WriteLine("/nTestCars2");      System.Console.WriteLine("----------");      var cars = new List<Car> { new Car(), new ConvertibleCar(),         new Minivan() };      foreach (var car in cars)      {        car.DescribeCar();        System.Console.WriteLine("----------");      }    }

輸出:

TestCars2----------Four wheels and an engine.Standard transportation.----------Four wheels and an engine.Standard transportation.----------Four wheels and an engine.Carries seven people.----------


    public static void TestCars3()    {      System.Console.WriteLine("/nTestCars3");      System.Console.WriteLine("----------");      ConvertibleCar car2 = new ConvertibleCar();      Minivan car3 = new Minivan();      car2.ShowDetails();      car3.ShowDetails();    }

輸出:       

TestCars3----------A roof that opens up.Carries seven people.

 

    public static void TestCars4()    {      System.Console.WriteLine("/nTestCars4");      System.Console.WriteLine("----------");      Car car2 = new ConvertibleCar();      Car car3 = new Minivan();      car2.ShowDetails();      car3.ShowDetails();    }    // Output:    // TestCars4    // ----------    // Standard transportation.    // Carries seven people.  }  // Define the base class, Car. The class defines two virtual methods,  // DescribeCar and ShowDetails. DescribeCar calls ShowDetails, and each derived  // class also defines a ShowDetails method. The example tests which version of  // ShowDetails is used, the base class method or the derived class method.  class Car  {    public virtual void DescribeCar()    {      System.Console.WriteLine("Four wheels and an engine.");      ShowDetails();    }    public virtual void ShowDetails()    {      System.Console.WriteLine("Standard transportation.");    }  }  // Define the derived classes.  // Class ConvertibleCar uses the new modifier to acknowledge that ShowDetails  // hides the base class method.  class ConvertibleCar : Car  {    public new void ShowDetails()    {      System.Console.WriteLine("A roof that opens up.");    }  }  // Class Minivan uses the override modifier to specify that ShowDetails  // extends the base class method.  class Minivan : Car  {    public override void ShowDetails()    {      System.Console.WriteLine("Carries seven people.");    }  }}

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
在线电影中文日韩| 亚洲精品久久久一区二区三区| 亚洲2020天天堂在线观看| 国产精品流白浆视频| 欧美成人精品在线视频| 欧美一级淫片videoshd| 亚洲精品视频免费在线观看| 国产一区二区三区在线| 亚洲国产第一页| 国产午夜精品美女视频明星a级| 亚洲级视频在线观看免费1级| 亚洲男女自偷自拍图片另类| 欧美电影电视剧在线观看| 高清在线视频日韩欧美| 欧美wwwxxxx| 8090成年在线看片午夜| 国产成人福利夜色影视| 欧美日韩国产一区二区三区| 亚洲国产古装精品网站| 最新亚洲国产精品| 亚洲午夜精品久久久久久性色| 欧美日韩激情小视频| 欧美亚洲午夜视频在线观看| 国产亚洲美女精品久久久| 97在线看免费观看视频在线观看| 久久精品最新地址| 亚洲综合精品伊人久久| 日韩av免费在线播放| 九九热精品视频| 亚洲性视频网址| 国产精品影院在线观看| 丝袜亚洲另类欧美重口| 日本一区二区在线免费播放| 在线观看91久久久久久| 亚洲欧洲在线播放| 日韩精品亚洲元码| 久久天天躁日日躁| www.欧美精品一二三区| 欧美日本黄视频| 91久久精品日日躁夜夜躁国产| 亚洲欧美国产日韩天堂区| 欧美高清视频在线| 日韩久久午夜影院| 午夜精品久久久久久99热软件| 亚洲欧美日韩国产精品| 久久精品亚洲94久久精品| 51色欧美片视频在线观看| 亚洲激情视频网站| 欧美性受xxx| 91理论片午午论夜理片久久| 亚洲成人网久久久| 日韩色av导航| 欧美最近摘花xxxx摘花| 91tv亚洲精品香蕉国产一区7ujn| 欧美日韩视频免费播放| 久久免费福利视频| 2019中文字幕在线免费观看| 懂色av影视一区二区三区| 欧美日韩中文字幕日韩欧美| 久久久久久亚洲精品中文字幕| 日本韩国在线不卡| 欧美裸体xxxx极品少妇| 亚洲精品久久久久| 久久久国产精彩视频美女艺术照福利| 91牛牛免费视频| 国产精品草莓在线免费观看| 欧美成人精品h版在线观看| 日韩欧美国产骚| 亚洲毛片一区二区| 亚洲精品国产精品国自产观看浪潮| 中文字幕亚洲一区二区三区| 国产精品一区二区三区免费视频| 日本伊人精品一区二区三区介绍| 成人h片在线播放免费网站| 国产精品直播网红| 成人自拍性视频| 91av在线看| 午夜精品一区二区三区视频免费看| 亚洲精品色婷婷福利天堂| 少妇高潮久久77777| 第一福利永久视频精品| 国产丝袜精品视频| 日韩精品日韩在线观看| 国产日韩在线亚洲字幕中文| 97国产一区二区精品久久呦| 欧美日韩国产色视频| 亚州欧美日韩中文视频| 久久亚洲国产精品| 伊人青青综合网站| 欧美电影在线观看高清| 亚洲激情视频在线| 亚洲精品日韩久久久| 大胆欧美人体视频| zzijzzij亚洲日本成熟少妇| 欧美激情亚洲一区| 日韩精品中文字幕视频在线| 国产成人一区二区在线| 欧美精品激情在线观看| 国产激情久久久久| 91精品久久久久久久久久另类| 日韩动漫免费观看电视剧高清| 国产精品盗摄久久久| 日韩av在线网页| 91麻豆国产精品| 日韩av三级在线观看| 亚洲加勒比久久88色综合| 伦理中文字幕亚洲| 日韩国产精品一区| 亚洲精品国产品国语在线| 日韩亚洲欧美中文在线| 欧美三级免费观看| x99av成人免费| 欧美性猛交xxxx久久久| 亚洲欧美中文日韩在线v日本| 97视频在线播放| 国产美女精彩久久| 狠狠久久五月精品中文字幕| 欧美精品久久久久久久免费观看| 91丝袜美腿美女视频网站| 亚洲国产精久久久久久| 国产精品自产拍在线观看中文| 久久久久久久久久久91| 成人午夜两性视频| 69av在线视频| 亚洲新声在线观看| 欧美性猛交xxxx久久久| 日本欧美一二三区| www国产91| 精品中文字幕久久久久久| 亚洲美女福利视频网站| 国产精品99蜜臀久久不卡二区| 久久精品这里热有精品| 亚洲天堂成人在线| 国产精品777| 国产精品久久久久久久久久久久久久| 欧美午夜性色大片在线观看| 日韩av中文在线| 久久精品国产99国产精品澳门| 国产精品久久久久久久久久新婚| 国产精品自产拍高潮在线观看| xxxxx成人.com| 国产精品99久久99久久久二8| 国产精品aaa| 精品久久久久久久久久久久久久| 尤物九九久久国产精品的特点| 91精品国产九九九久久久亚洲| 高清一区二区三区四区五区| 97超级碰在线看视频免费在线看| 国产精品免费视频久久久| 久久九九全国免费精品观看| 91精品国产免费久久久久久| 91精品久久久久久综合乱菊| 91精品久久久久| 亚洲女人被黑人巨大进入al| 69国产精品成人在线播放| 久久激情视频久久| 91精品在线国产| 欧美大全免费观看电视剧大泉洋| 亚洲一区中文字幕在线观看| 亚洲激情 国产| 国产精品美女视频网站| 亚洲成人黄色在线| 亚洲视频网站在线观看| 国产精品99久久久久久www|