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

C++ Programmer's Cookbook

{C++ 基礎} {C++ 高級} {C#界面,C++核心算法} {設計模式} {C#基礎}

C++ casting

Q: What are the C++ casting operators?

A: Casting means you change the representation of a variable by changing its type to a different one. In order to type-cast a simple object to another you use the traditional type casting operator. For example, to cast a floating point number of type 'double' to an integer of type 'int':

#include <typeinfo>

Code:

int i;
double d;

i = (int) d;
or also


Code:

i = int (d);
This is quite good for basic types that have standard defined conversions, however this operators can also been indiscriminately applied on classes and pointers to classes. ANSI-C++ standard has defined four new casting operators: 'reinterpret_cast', 'static_cast', 'dynamic_cast' and 'const_cast' in order to control these types of conversions between classes...


Code:
reinterpret_cast<new_type>(expression)
Code:
static_cast<new_type>(expression)
Code:
dynamic_cast<new_type>(expression)
Code:
const_cast<new_type>(expression)

'reinterpret_cast'

'reinterpret_cast' casts a pointer to any other type of pointer. It also allows casting from pointer to an integer type and vice versa.

This operator can cast pointers between non-related classed. The operation results is a simple binary copy of the value from a pointer to the other. The content pointed does not pass any kind of check nor transformation between types.

In the case that the copy is performed from a pointer to an integer, the interpretation of its content is system dependent and therefore any implementation is non portable. A pointer casted to an integer enough large to fully contain it can be casted back to a valid pointer.


Code:

class A {};
class B {};

A * a = new A;
B * b = reinterpret_cast<B *>(a);
'reinterpret_cast' treats all pointers exactly as traditional type-casting operators do.


'static_cast'

'static_cast' allows to perform any casting that can be implicitly performed as well as also the inverse cast (even if this is not allowed implicitly).

Applied to pointers to classes, that is to say that it allows to cast a pointer of a derived class to its base class (this is a valid conversion that can be implicitly performed) and can also perform the inverse: cast a base class to its derivated class.

In this last case the base class that is being casted is not checked to determine wether this is a complete class of the destination type or not.


Code:

class Base {};
class Derived : public Base {};

Base *a    = new Base;
Derived *b = static_cast<Derived *>(a);
'static_cast', aside from manipulating pointers to classes, can also be used to perform conversions explicitly defined in classes, as well as to perform standard conversions between fundamental types:


Code:

double d = 3.14159265;
int    i = static_cast<int>(d);


'dynamic_cast'

'dynamic_cast' is exclusively used with pointers and references to objects. It allows any type-casting that can be implicitly performed as well as the inverse one when used with polymorphic classes, however, unlike static_cast, dynamic_cast checks, in this last case, if the operation is valid. That is to say, it checks if the casting is going to return a valid complete object of the requested type.

Checking is performed during run-time execution. If the pointer being casted is not a pointer to a valid complete object of the requested type, the value returned is a 'NULL' pointer.


Code:

class Base { virtual dummy() {} };
class Derived : public Base {};

Base* b1 = new Derived;
Base* b2 = new Base;

Derived* d1 = dynamic_cast<Derived *>(b1);          // succeeds
Derived* d2 = dynamic_cast<Derived *>(b2);          // fails: returns 'NULL'
If the type-casting is performed to a reference type and this casting is not possible an exception of type 'bad_cast' is thrown:


Code:

class Base { virtual dummy() {} };
class Derived : public Base { };

Base* b1 = new Derived;
Base* b2 = new Base;

Derived d1 = dynamic_cast<Derived &*>(b1);          // succeeds
Derived d2 = dynamic_cast<Derived &*>(b2);          // fails: exception thrown


'const_cast'

This type of casting manipulates the const attribute of the passed object, either to be set or removed:


Code:

class C {};

const C *a = new C;

C *b = const_cast<C *>(a);
Neither of the other three new cast operators can modify the constness of an object.

Note: The 'const_cast' operator can also change the 'volatile' qualifier on a type.


typeid  得到類對象或指針

typeid(*pb).name()   輸出對象名
 
typeid(pb).name()     輸出類名

 

---------子類向基類私有或保護繼承的時,可以轉化但是不能訪問。 一般不進行轉化。error 2443



------------------------------------------------------------------------------------
C++風格的轉型運算符小結

為了改正C中丑陋的轉型操作,C++中引入了四個新的轉型操作符,分別是:
dynamic_cast
const_cast
static_cast
reinterpret_cast

1.dynamic_cast
這個轉型操作符主要用在安全的向下轉型(safe downcasting)中,也就是從基類指針/引用向派生類指針/引用的轉型。例如:
Code: [View More of this Code] [View Even More of this Code] [View Less of this Code] [Select All of this Code]

class A {...};
class B:public A {...};
A* a = new B;
B* b;
b = dynamic_cast<B *> a;

當你將dynamic_cast用在指針上時,如果成功,就傳回一個轉型目標的指針,如果失敗,則傳回null指針。所以用到dynamic_cast的時候必然會導致if-then-else的程序風格,其中else就是用來檢測轉型失敗的情況([1]第39條)。例子如下:
Code: [View More of this Code] [View Even More of this Code] [View Less of this Code] [Select All of this Code]
#include <iostream>
using namespace std;

class A {
public:
 virtual void do_sth(){
  cout<<"aaa\n";
 }

};
class B : public A {
public:
 virtual void do_sth(){
  cout<<"bbb\n";
 }

};
class C : public A {
public:
 virtual void do_sth(){
  cout<<"ccc\n";
 }
 
};

int main(){
 A* a1 = new B;
 A* a2 = new C;
 B* b;

 if(b = dynamic_cast<B *>(a1))//轉換成功
  b->do_sth();
 else
  cout<<"error\n";
 
 if(b = dynamic_cast<B *>(a2))//轉換失敗
  b->do_sth();
 else
  cout<<"error\n";
}


2.const_cast
此轉型操作符用來將對象或指針的常量性(sonstness)轉型掉。例如:

const A * a1;
A * a2 = const_cast<A *> (a1);

需要注意的是,const_cast轉型并不總是成功的,當遇到轉型的對象本身就是const的時候,那么將其常量性轉型,結果未定義。看一下下面的例子:
Code: [View More of this Code] [View Even More of this Code] [View Less of this Code] [Select All of this Code]

// constcast.cpp from [2]
#include <iostream>
using std::cout;

void change(const int * pt, int n);

int main()
{
    int pop1 = 38383;
    const int pop2 = 2000;

    cout << "pop1, pop2: " << pop1 << ", " << pop2 << '\n';
    change(&pop1, -1);
    change(&pop2, -1);
    cout << "pop1, pop2: " << pop1 << ", " << pop2 << '\n';

    return 0;
}

void change(const int * pt, int n)
{
    int * pc;
    if (n < 0)
    {
        pc = const_cast<int *>(pt);
        *pc = 100;
    }
}

輸出的結果是:
pop1, pop2: 38383, 2000
pop1, pop2: 100, 2000
可見,pop2的值并沒有改變(有些編譯器會產生一個pop2的臨時變量,并將其地址值賦給pc。在C++標準中,這種情況下的行為是不確定的[2])。

3.static_cast
此轉型操作符用于內建數據類型之間的轉型。它與C的轉型操作最接近。當沒有其他適當的轉型操作符可用時,就使用它。它可以將整型轉換為枚舉型,雙精度型轉換為整型,浮點型轉換為長整型等等。例如:
Code: [View More of this Code] [View Even More of this Code] [View Less of this Code] [Select All of this Code]

    int n=9;
    double d = static_cast < double > (n);

上面的例子中,我們將一個變量從 int 轉換到 double. 這些類型的二進制表達式是不同的。要將整數 9 轉換到 雙精度整數 9,static_cast需要正確地為雙精度整數 d 補足比特位。其結果為 9.0 。

4.reinterpret_cast
此轉型操作符的結果取決于編譯器,用于修改操作數類型,非類型安全的轉換符。舉例如下:
Code: [View More of this Code] [View Even More of this Code] [View Less of this Code] [Select All of this Code]

int main() { // from [2]
    struct dat { short a; short b;};
    long value = 0xA224B118;
    dat * pd = reinterpret_cast<dat *> (&value);
    cout << pd->a;   // display first 2 bytes of value
    return 0;
}

該例中將long型轉換成struct,但此代碼是不可移植的,在IBM兼容機和Mac機上的運行結果完全不一樣,因為他們存儲字節的方式不一樣。
reinterpret_cast的使用要非常的謹慎,例如將3中的例子改寫如下:
Code: [View More of this Code] [View Even More of this Code] [View Less of this Code] [Select All of this Code]

    int n=9;
    double d = reinterpret_cast<double & > (n);
  

這次,與3的結果有所不同。在進行計算以后,d 包含無用值。這是因為 reinterpret_cast 僅僅是復制 n 的比特位到 d,沒有進行必要的分析。

以上是我在學習這些轉型操作符一個小結,如有不對之處,請各位不嗇賜教。
大家有興趣,可以去這里做一下有關這些轉型操作符的練習。

注:以上例子在 VC6 + Intel C++ Compiler 8.0 下編譯運行通過(別忘了打開RTTI,加參數/GR)。

參考文獻:
[1] Effective C++ 中文版 Scott Meyers 侯捷譯
[2] C++ Primer Plus, 4th Edition, Stephen Prata
[3] STATIC_CAST VERSUS REINTERPRET_CAST(Topica轉載)


----------------------------------
這是More Effecitve C++里的第二條對類型轉換講的很好,也很基礎好懂。
Item M2:盡量使用C++風格的類型轉換
仔細想想地位卑賤的類型轉換功能(cast),其在程序設計中的地位就象goto語句一樣令人鄙視。但是它還不是無法令人忍受,因為當在某些緊要的關頭,類型轉換還是必需的,這時它是一個必需品。
不過C風格的類型轉換并不代表所有的類型轉換功能。
       一、來它們過于粗魯,能允許你在任何類型之間進行轉換。不過如果要進行更精確的類型轉換,這會是一個優點。在這些類型轉換中存在著巨大的不同,例如把一個指向 const對象的指針(pointer-to-const-object)轉換成指向非const對象的指針(pointer-to-non-const -object)(即一個僅僅去除const的類型轉換),把一個指向基類的指針轉換成指向子類的指針(即完全改變對象類型)。傳統的C風格的類型轉換不對上述兩種轉換進行區分。(這一點也不令人驚訝,因為C風格的類型轉換是為C語言設計的,而不是為C++語言設計的)。
      二、來C 風格的類型轉換在程序語句中難以識別。在語法上,類型轉換由圓括號和標識符組成,而這些可以用在C++中的任何地方。這使得回答象這樣一個最基本的有關類型轉換的問題變得很困難:“在這個程序中是否使用了類型轉換?”。這是因為人工閱讀很可能忽略了類型轉換的語句,而利用象grep的工具程序也不能從語句構成上區分出它們來。
C++通過引進四個新的類型轉換操作符克服了C風格類型轉換的缺點,這四個操作符是, static_cast, const_cast, dynamic_cast, 和reinterpret_cast。在大多數情況下,對于這些操作符你只需要知道原來你習慣于這樣寫,
(type) expression
而現在你總應該這樣寫:
static_cast<type>(expression)
例如,假設你想把一個int轉換成double,以便讓包含int類型變量的表達式產生出浮點數值的結果。如果用C風格的類型轉換,你能這樣寫:
int firstNumber, secondNumber;
...
double result = ((double)firstNumber)/secondNumber;
如果用上述新的類型轉換方法,你應該這樣寫:
double result = static_cast<double>(firstNumber)/secondNumber;
這樣的類型轉換不論是對人工還是對程序都很容易識別。
static_cast 在功能上基本上與C風格的類型轉換一樣強大,含義也一樣。它也有功能上限制。例如,你不能用static_cast象用C風格的類型轉換一樣把 struct轉換成int類型或者把double類型轉換成指針類型,另外,static_cast不能從表達式中去除const屬性,因為另一個新的類型轉換操作符const_cast有這樣的功能。
其它新的C++類型轉換操作符被用在需要更多限制的地方。const_cast用于類型轉換掉表達式的const或volatileness屬性。通過使用const_cast,你向人們和編譯器強調你通過類型轉換想做的只是改變一些東西的 constness或者volatileness屬性。這個含義被編譯器所約束。如果你試圖使用const_cast來完成修改constness 或者volatileness屬性之外的事情,你的類型轉換將被拒絕。下面是一些例子:
class Widget { ... };
class SpecialWidget: public Widget { ... };
void update(SpecialWidget *psw);
SpecialWidget sw; // sw 是一個非const 對象。
const SpecialWidget& csw = sw; // csw 是sw的一個引用
// 它是一個const 對象
update(&csw); // 錯誤!不能傳遞一個const SpecialWidget* 變量
// 給一個處理SpecialWidget*類型變量的函數
update(const_cast<SpecialWidget*>(&csw));
// 正確,csw的const被顯示地轉換掉(
// csw和sw兩個變量值在update
//函數中能被更新)
update((SpecialWidget*)&csw);
// 同上,但用了一個更難識別
//的C風格的類型轉換
Widget *pw = new SpecialWidget;
update(pw); // 錯誤!pw的類型是Widget*,但是
// update函數處理的是SpecialWidget*類型
update(const_cast<SpecialWidget*>(pw));
// 錯誤!const_cast僅能被用在影響
// constness or volatileness的地方上。,
// 不能用在向繼承子類進行類型轉換?br> 到目前為止,const_cast最普通的用途就是轉換掉對象的const屬性。
第二種特殊的類型轉換符是dynamic_cast,它被用于安全地沿著類的繼承關系向下進行類型轉換。這就是說,你能用dynamic_cast把指向基類的指針或引用轉換成指向其派生類或其兄弟類的指針或引用,而且你能知道轉換是否成功。失敗的轉換將返回空指針(當對指針進行類型轉換時)或者拋出異常(當對引用進行類型轉換時):
Widget *pw;
...
update(dynamic_cast<SpecialWidget*>(pw));
// 正確,傳遞給update函數一個指針
// 是指向變量類型為SpecialWidget的pw的指針
// 如果pw確實指向一個對象,
// 否則傳遞過去的將使空指針。
void updateViaRef(SpecialWidget& rsw);
updateViaRef(dynamic_cast<SpecialWidget&>(*pw));
//正確。傳遞給updateViaRef函數
// SpecialWidget pw 指針,如果pw
// 確實指向了某個對象
// 否則將拋出異常
dynamic_casts在幫助你瀏覽繼承層次上是有限制的。它不能被用于缺乏虛函數的類型上(參見條款M24),也不能用它來轉換掉constness:
int firstNumber, secondNumber;
...
double result = dynamic_cast<double>(firstNumber)/secondNumber;
// 錯誤!沒有繼承關系
const SpecialWidget sw;
...
update(dynamic_cast<SpecialWidget*>(&sw));
// 錯誤! dynamic_cast不能轉換
// 掉const。
如你想在沒有繼承關系的類型中進行轉換,你可能想到static_cast。如果是為了去除const,你總得用const_cast。
這四個類型轉換符中的最后一個是reinterpret_cast。使用這個操作符的類型轉換,其的轉換結果幾乎都是執行期定義(implementation-defined)。因此,使用reinterpret_casts的代碼很難移植。
reinterpret_casts的最普通的用途就是在函數指針類型之間進行轉換。例如,假設你有一個函數指針數組:
typedef void (*FuncPtr)(); // FuncPtr is 一個指向函數
// 的指針,該函數沒有參數
// 返回值類型為void
FuncPtr funcPtrArray[10]; // funcPtrArray 是一個能容納
// 10個FuncPtrs指針的數組
讓我們假設你希望(因為某些莫名其妙的原因)把一個指向下面函數的指針存入funcPtrArray數組:
int doSomething();
你不能不經過類型轉換而直接去做,因為doSomething函數對于funcPtrArray數組來說有一個錯誤的類型。在FuncPtrArray數組里的函數返回值是void類型,而doSomething函數返回值是int類型。
funcPtrArray[0] = &doSomething; // 錯誤!類型不匹配
reinterpret_cast可以讓你迫使編譯器以你的方法去看待它們:
funcPtrArray[0] = // this compiles
reinterpret_cast<FuncPtr>(&doSomething);
轉換函數指針的代碼是不可移植的(C++不保證所有的函數指針都被用一樣的方法表示),在一些情況下這樣的轉換會產生不正確的結果(參見條款M31),所以你應該避免轉換函數指針類型,除非你處于著背水一戰和尖刀架喉的危急時刻。一把鋒利的刀。一把非常鋒利的刀。
如果你使用的編譯器缺乏對新的類型轉換方式的支持,你可以用傳統的類型轉換方法代替static_cast, const_cast, 以及reinterpret_cast。也可以用下面的宏替換來模擬新的類型轉換語法:
#define static_cast(TYPE,EXPR) ((TYPE)(EXPR))
#define const_cast(TYPE,EXPR) ((TYPE)(EXPR))
#define reinterpret_cast(TYPE,EXPR) ((TYPE)(EXPR))
你可以象這樣使用使用:
double result = static_cast(double, firstNumber)/secondNumber;
update(const_cast(SpecialWidget*, &sw));
funcPtrArray[0] = reinterpret_cast(FuncPtr, &doSomething);
這些模擬不會象真實的操作符一樣安全,但是當你的編譯器可以支持新的的類型轉換時,它們可以簡化你把代碼升級的過程。
沒有一個容易的方法來模擬dynamic_cast的操作,但是很多函數庫提供了函數,安全地在派生類與基類之間進行類型轉換。如果你沒有這些函數而你有必須進行這樣的類型轉換,你也可以回到C風格的類型轉換方法上,但是這樣的話你將不能獲知類型轉換是否失敗。當然,你也可以定義一個宏來模擬 dynamic_cast的功能,就象模擬其它的類型轉換一樣:
#define dynamic_cast(TYPE,EXPR) (TYPE)(EXPR)
請記住,這個模擬并不能完全實現dynamic_cast的功能,它沒有辦法知道轉換是否失敗。
我知道,是的,我知道,新的類型轉換操作符不是很美觀而且用鍵盤鍵入也很麻煩。如果你發現它們看上去實在令人討厭,C風格的類型轉換還可以繼續使用并且合法。然而,正是因為新的類型轉換符缺乏美感才能使它彌補了在含義精確性和可辨認性上的缺點。并且,使用新類型轉換符的程序更容易被解析(不論是對人工還是對于工具程序),它們允許編譯器檢測出原來不能發現的錯誤。這些都是放棄C風格類型轉換方法的強有力的理由。還有第三個理由:也許讓類型轉換符不美觀和鍵入麻煩是一件好事。

posted on 2005-11-09 13:02 夢在天涯 閱讀(1939) 評論(2)  編輯 收藏 引用 所屬分類: CPlusPlus

評論

# re: C++ casting 2006-09-29 12:30 一雨田

typeid只能得到類名,不可以得到對象名。  回復  更多評論   

# re: C++ casting 2011-07-05 22:24 renwotao

可以得到對象名typeid(類名).name()@一雨田
  回復  更多評論   

公告

EMail:itech001#126.com

導航

統計

  • 隨筆 - 461
  • 文章 - 4
  • 評論 - 746
  • 引用 - 0

常用鏈接

隨筆分類

隨筆檔案

收藏夾

Blogs

c#(csharp)

C++(cpp)

Enlish

Forums(bbs)

My self

Often go

Useful Webs

Xml/Uml/html

搜索

  •  

積分與排名

  • 積分 - 1812202
  • 排名 - 5

最新評論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
              国产欧美婷婷中文| 亚洲午夜一区| 中文日韩在线| 亚洲美洲欧洲综合国产一区| 亚洲国产欧美国产综合一区| 亚洲第一免费播放区| 亚洲电影自拍| 亚洲美女色禁图| 亚洲一区二区三区在线观看视频| 久久久综合免费视频| 欧美激情亚洲视频| 欧美日韩mp4| 你懂的成人av| 亚洲激情电影在线| 免费精品视频| 日韩一级片网址| 亚洲欧美欧美一区二区三区| 欧美中文在线视频| 久久亚洲精品网站| 欧美日韩小视频| 好吊视频一区二区三区四区| 亚洲伦理久久| 欧美一区二区视频在线观看2020| 久久中文字幕导航| av成人天堂| 久久久欧美一区二区| 欧美日韩精品一区二区三区| 国产一区二区三区在线观看免费视频 | 亚洲精品国产精品国自产观看| 日韩视频在线免费| 性久久久久久久久| 欧美日韩综合视频| 亚洲福利精品| 欧美中文日韩| 亚洲另类春色国产| 久久亚洲私人国产精品va媚药| 欧美日韩综合一区| 亚洲精品影视在线观看| 欧美在线国产| 日韩午夜激情| 欧美电影免费观看| 精品成人a区在线观看| 亚洲伊人一本大道中文字幕| 欧美成人午夜激情视频| 亚洲婷婷综合久久一本伊一区| 免费成人黄色| 在线观看亚洲精品视频| 欧美自拍丝袜亚洲| 宅男精品视频| 欧美视频在线观看视频极品| 亚洲三级视频| 欧美激情小视频| 久久精品视频播放| 国产亚洲女人久久久久毛片| 午夜视频一区| 中文精品视频| 国产精品久久久久久久久免费桃花 | 久久综合色综合88| 国产一区二区久久久| 久久中文字幕导航| 亚洲激情在线视频| 久久九九精品99国产精品| 这里只有精品丝袜| 欧美日韩一区二区视频在线观看| 亚洲人被黑人高潮完整版| 欧美成年人视频网站| 久久人人97超碰精品888| 在线播放日韩欧美| 久久精品二区三区| 欧美在线观看视频在线| 国产一区二区三区av电影| 久久人人爽国产| 久久视频精品在线| 亚洲国产福利在线| 欧美成黄导航| 欧美一区二区三区视频在线| 亚洲精品欧洲精品| 欧美日本一道本在线视频| 亚洲精品精选| 亚洲永久网站| 激情校园亚洲| 亚洲国产小视频在线观看| 欧美经典一区二区三区| 国产精品日本| 欧美一区亚洲二区| 久久激情综合| 亚洲福利视频免费观看| 欧美阿v一级看视频| 女人天堂亚洲aⅴ在线观看| 亚洲成色精品| 欧美国产一区二区| 欧美日韩精品伦理作品在线免费观看| 一区二区三区免费网站| 亚洲图片在区色| 伊人蜜桃色噜噜激情综合| 亚洲人成在线影院| 国产日韩精品一区二区| 久色婷婷小香蕉久久| 免费在线亚洲欧美| 久久精品免费电影| 欧美精品18videos性欧美| 欧美午夜不卡在线观看免费 | 欧美激情中文不卡| 亚洲欧美日本另类| 久久国内精品视频| 亚洲人成在线观看| 亚洲欧美激情精品一区二区| 在线看国产日韩| 99视频精品全国免费| 一区二区三区在线不卡| 久久国产精彩视频| 国产一区导航| 日韩视频中文字幕| 狠狠88综合久久久久综合网| 91久久综合| 国产亚洲欧美一区二区三区| 亚洲激情成人在线| 狠狠色丁香婷婷综合久久片| 一本色道88久久加勒比精品| 亚洲国产精品黑人久久久| 亚洲综合色自拍一区| 一本色道久久99精品综合| 久久久久久穴| 欧美一区二区女人| 欧美精品1区| 欧美成人一区二区在线| 狠狠色伊人亚洲综合网站色| 亚洲主播在线| 亚洲欧美综合国产精品一区| 欧美精品久久久久a| 免费观看一区| 亚洲资源av| 一区二区精品在线观看| 蜜桃av一区| 久久久精品日韩| 国产日韩欧美夫妻视频在线观看| 亚洲人成网站色ww在线| 亚洲人在线视频| 男人的天堂亚洲| 欧美激情影音先锋| 亚洲激情婷婷| 欧美激情女人20p| 亚洲级视频在线观看免费1级| 在线不卡视频| 欧美69wwwcom| 亚洲精品在线免费| 在线视频精品一| 欧美视频久久| 午夜精品一区二区三区在线视| 亚洲欧美清纯在线制服| 国产精品一区在线观看| 亚洲欧美春色| 麻豆91精品91久久久的内涵| 在线电影国产精品| 欧美a级一区| 亚洲精品美女在线| 亚洲一级网站| 国产丝袜美腿一区二区三区| 欧美亚洲尤物久久| 媚黑女一区二区| 亚洲精品免费一区二区三区| 欧美日韩系列| 欧美一区2区三区4区公司二百| 久久理论片午夜琪琪电影网| 亚洲国产精品激情在线观看| 欧美精品1区2区| 亚洲图中文字幕| 久久综合九色九九| 亚洲美洲欧洲综合国产一区| 国产精品三级久久久久久电影| 欧美在线播放高清精品| 亚洲成人在线视频网站| 亚洲性视频网址| 国产综合久久久久久鬼色| 久久久久九九视频| 亚洲黄色三级| 欧美主播一区二区三区| 亚洲日本无吗高清不卡| 国产精品日本欧美一区二区三区| 亚洲精品视频免费| 亚洲人成在线播放| 欧美福利在线观看| 亚洲免费在线| 国产一区视频网站| 欧美一区网站| 欧美激情免费在线| 亚洲一区免费观看| 久久人91精品久久久久久不卡| 亚洲欧美激情四射在线日| 亚洲国产精品嫩草影院| 欧美中在线观看| 午夜日韩在线| 欧美体内谢she精2性欧美| 亚洲欧洲一二三| 亚洲欧洲一区| 久久国产精品99国产| 久久一区中文字幕| 亚洲高清毛片| 欧美另类女人| 亚洲欧美变态国产另类|