static_cast <> และการหล่อสไตล์ C แตกต่างกันอย่างไร


202

มีเหตุผลใดที่จะชอบstatic_cast<>การคัดเลือกนักแสดงสไตล์ C มากกว่าหรือไม่? พวกเขาเท่ากันหรือไม่ การเรียงลำดับความเร็วแตกต่างกันหรือไม่?


5
ที่เกี่ยวข้อง: stackoverflow.com/questions/103512/…
Flow

คำตอบ:


217

การร่ายสไตล์ C ++ นั้นได้รับการตรวจสอบโดยคอมไพเลอร์ รูปแบบ C ใช้งานไม่ได้และอาจล้มเหลวขณะทำงาน

นอกจากนี้สไตล์ c ++ สามารถค้นหาได้ง่ายในขณะที่มันยากที่จะค้นหาสไตล์ c

ประโยชน์ที่ยิ่งใหญ่อีกประการหนึ่งคือสไตล์ C ++ ที่แตกต่างกัน 4 รูปแบบแสดงถึงเจตนาของโปรแกรมเมอร์ชัดเจนยิ่งขึ้น

เมื่อเขียน C ++ ฉันมักจะใช้ C ++ กับสไตล์ C เสมอ


67
cast ที่เดียวที่สามารถล้มเหลวขณะรันไทม์คือdynamic_casts
R. Martinho Fernandes

12
C ++ reinterpret_cast <T> (U) สามารถล้มเหลวได้ในเวลาทำงานค่อนข้างคล้ายกับการโยนสไตล์ C และพวกเขาก็ค่อนข้างแตกต่างจากการที่ dynamic_cast <T> (U) ล้มเหลว
Christopher Smith

20
cast1 C ธรรมดา(int)somethingไม่สามารถล้มเหลวได้ - คุณได้รับการร่ายไปยังข้อผิดพลาด int หรือคอมไพเลอร์
Tomáš Zato - Reinstate Monica

2
คุณช่วยอธิบายเพิ่มเติมได้ไหมว่าเพราะเหตุใด C ++ cast จึงถูกค้นหาได้ง่ายกว่า C casts?
Minh Tran

3
@MinhTran สำหรับสไตล์ C ++ คุณสามารถค้นหาคำหลัก "ส่ง" ผ่านไฟล์ต้นฉบับของคุณ แต่คุณอยากทำอะไรกับ c-style cast?
huangzonghao

176

ในระยะสั้น :

  1. static_cast<>() ช่วยให้คุณมีความสามารถในการตรวจสอบเวลาคอมไพล์ C-Style cast ไม่ได้
  2. static_cast<>() สามารถอ่านได้มากขึ้นและสามารถเห็นได้ง่ายทุกที่ในรหัสที่มา C ++, C_Style cast is'nt
  3. ความตั้งใจจะถ่ายทอดได้ดีขึ้นโดยใช้ C + + casts

คำอธิบายเพิ่มเติม :

คงโยนแปลงดำเนินการระหว่างประเภทที่เข้ากันได้ มันคล้ายกับตัวละครสไตล์ C แต่มีข้อ จำกัด มากกว่า ยกตัวอย่างเช่นตัวละครสไตล์ C จะอนุญาตให้ตัวชี้จำนวนเต็มชี้ไปที่อักขระ

char c = 10;       // 1 byte
int *p = (int*)&c; // 4 bytes

เนื่องจากสิ่งนี้ส่งผลให้ตัวชี้แบบ 4 ไบต์ (ตัวชี้ไปยังประเภทข้อมูลแบบ 4 ไบต์) ชี้ไปที่ 1 ไบต์ของหน่วยความจำที่จัดสรรการเขียนไปยังตัวชี้นี้จะทำให้เกิดข้อผิดพลาดขณะทำงานหรือจะเขียนทับหน่วยความจำบางส่วน

*p = 5; // run-time error: stack corruption

ตรงกันข้ามกับตัว C-style คาสต์คงที่จะอนุญาตให้คอมไพเลอร์ตรวจสอบว่าตัวชี้และชนิดข้อมูลพอยต์เข้ากันได้ซึ่งช่วยให้โปรแกรมเมอร์จับการกำหนดตัวชี้ที่ไม่ถูกต้องนี้ในระหว่างการรวบรวม

int *q = static_cast<int*>(&c); // compile-time error

คุณสามารถตรวจสอบหน้านี้เพื่ออธิบายเพิ่มเติมเกี่ยวกับ C ++ casts: คลิกที่นี่


17
ฉันคิดว่าแทนที่จะเป็น "ตัวชี้ 4 ไบต์" คุณหมายถึง "ตัวชี้ไปยังประเภทข้อมูล 4 ไบต์"
iheanyi

แต่มันยอมให้ int q = static_cast <int> (c);
TonyParker

3
@ TonyParker นั่นเป็นเพราะไม่มีอะไรผิดปกติกับบรรทัดนั้น
Braden ที่ดีที่สุด

15

ดูการเปรียบเทียบของ C ++ ผู้ประกอบการหล่อ

อย่างไรก็ตามการใช้ไวยากรณ์เดียวกันสำหรับการดำเนินการร่ายที่แตกต่างกันสามารถทำให้เจตนาของโปรแกรมเมอร์ไม่ชัดเจน

ยิ่งไปกว่านั้นมันอาจเป็นเรื่องยากที่จะค้นหาประเภทของการหล่อในรหัสเบสขนาดใหญ่

ลักษณะทั่วไปของการขว้าง C-style สามารถ overkill สำหรับสถานการณ์ที่ทุกอย่างที่ต้องการคือการแปลงอย่างง่าย ความสามารถในการเลือกระหว่างผู้ดำเนินการหล่อที่แตกต่างกันหลายระดับพลังงานที่แตกต่างกันสามารถป้องกันโปรแกรมเมอร์จากการหล่อโดยไม่ตั้งใจไปยังประเภทที่ไม่ถูกต้อง


14
struct A {};
struct B : A {};
struct C {}; 

int main()
{
    A* a = new A;    

    int i = 10;

    a = (A*) (&i); // NO ERROR! FAIL!

    //a = static_cast<A*>(&i); ERROR! SMART!

    A* b = new B;

    B* b2 = static_cast<B*>(b); // NO ERROR! SMART!

    C* c = (C*)(b); // NO ERROR! FAIL!

    //C* c = static_cast<C*>(b); ERROR! SMART!
}

5
คุณช่วยอธิบายรายละเอียดเพิ่มเติมเกี่ยวกับโซลูชันที่คุณให้ได้ไหม
abarisone

1
ฉันคิดว่าคำตอบแสดงให้เห็นว่า "static_casts" ตรวจสอบการแปลงประเภทเพื่อให้แน่ใจว่าพวกเขาอยู่ในเส้นทางที่ถูกต้องในกราฟลำดับชั้น ในตัวอย่างนี้อนุญาตให้ทำการแคสต์จาก A * ถึง B * หรือ B * ถึง A * ได้เนื่องจาก A และ B จัดทำพา ธ ในกราฟลำดับชั้น C * ไม่ได้อยู่ในเส้นทางดังนั้น static_cast จะสร้างข้อผิดพลาดในการรวบรวมเวลา Sidenote: มันอาจจะคุ้มค่าที่จะสังเกตว่าการคัดเลือกจาก A * ถึง B * อาจส่งผลให้ NULL มีค่า dynamic_cast ณ รันไทม์ขึ้นอยู่กับวัตถุต้นแบบจริง
ทอมมี่เฉิน

7

โพสต์ที่ยอดเยี่ยมที่อธิบายการปลดเปลื้องที่แตกต่างกันใน C / C ++ และสิ่งที่นักแสดงในรูปแบบ C ทำได้จริง: https://anteru.net/blog/2007/12/18/200/index.html

การคัดเลือกแบบ C-Style โดยใช้ไวยากรณ์ตัวแปร (ชนิด) ที่เลวร้ายที่สุดที่เคยประดิษฐ์ นี้พยายามที่จะทำมันได้ปลดเปลื้องต่อไปนี้ตามลำดับนี้: (ดูมาตรฐาน C ++, 5.4 expr.cast วรรค 5)

  1. const_cast
  2. static_cast
  3. static_cast ตามด้วย const_cast
  4. reinterpret_cast
  5. reinterpret_castfollowed โดย const_cast

5

static_castตรวจสอบ ณ เวลารวบรวมว่าการแปลงนั้นไม่อยู่ระหว่างประเภทที่เข้ากันไม่ได้ ตรงกันข้ามdynamic_castไม่มีการตรวจสอบความเข้ากันได้ของชนิดในขณะใช้งาน นอกจากนี้static_castการแปลงไม่จำเป็นต้องปลอดภัย

static_cast ใช้ในการแปลงจากตัวชี้ไปยังคลาสพื้นฐานเป็นตัวชี้ไปยังคลาสที่ได้รับหรือระหว่างชนิดเนทีฟเช่น enum เป็น int หรือ float เป็น int

ผู้ใช้static_castต้องแน่ใจว่าการแปลงนั้นปลอดภัย

คาสต์ C-style ไม่ทำการตรวจสอบใด ๆ


3

static_cast <> ช่วยให้คุณพูดว่า "ฉันใช้การแปลงทางกฎหมายจากประเภทหนึ่งไปยังอีกประเภทหนึ่ง" มีหลายประเภทที่แตกต่างกันในแต่ละความหมาย การหล่อแบบ C ธรรมดาอาจมีความหมายหลายอย่าง คุณหล่อขึ้น / ลงหรือไม่ คุณกำลังตีความตัวชี้ซ้ำหรือไม่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.