phôi kiểu c hoặc phôi kiểu c ++


21

Vì vậy, những gì bạn sử dụng?

int anInt = (int)aFloat;

hoặc là

int anInt = static_cast<int>(aFloat);
// and its brethren

Và, quan trọng hơn, tại sao?

Câu trả lời:


45

Đầu tiên, hãy hiểu rằng những dòng đó không tương đương .

int* anInt = (int*)aFloat; // is equivalent to

int* anInt = reinterpret_cast<int*>(aFloat); 

Điều đang xảy ra ở đây là lập trình viên đang yêu cầu trình biên dịch làm bất cứ điều gì có thể để tạo dàn diễn viên.

Sự khác biệt rất quan trọng vì sử dụng static_cast sẽ chỉ yêu cầu loại cơ sở "an toàn" để chuyển đổi sang, trong đó reinterpret_cast sẽ chuyển đổi thành bất cứ thứ gì, có thể chỉ bằng cách ánh xạ bố cục bộ nhớ mong muốn qua bộ nhớ của đối tượng đã cho.

Vì vậy, vì "bộ lọc" không giống nhau, nên sử dụng cast cụ thể sẽ rõ ràng và an toàn hơn so với sử dụng cast C, nếu bạn dựa vào trình biên dịch (hoặc impl impl. Nếu bạn sử dụng Dynamic_cast) để cho bạn biết bạn đã làm gì sai , bằng cách tránh C cast và reinterepret_cast.

Bây giờ điều này đã rõ ràng hơn, có một điều khác: static_cast, reinterpret_cast, const_cast và Dynamic_cast dễ dàng tìm kiếm hơn .

Và điểm cuối cùng: chúng xấu xí . Đó là muốn. Mã lỗi tiềm ẩn, mùi mã, "thủ thuật" rõ ràng có thể tạo ra lỗi, dễ theo dõi hơn khi liên quan đến giao diện xấu. Mã xấu nên xấu .

Đó là "theo thiết kế". Và điều đó cho phép nhà phát triển biết nơi anh ta có thể làm mọi thứ tốt hơn (bằng cách tránh hoàn toàn diễn viên, nếu không thực sự cần thiết) và nơi nào tốt nhưng nó "được ghi lại" trong mã bằng cách "đánh dấu" nó là xấu xí.

Một lý do thứ yếu để giới thiệu dàn diễn viên theo phong cách mới là dàn diễn viên kiểu C rất khó nhận ra trong một chương trình. Ví dụ: bạn không thể thuận tiện tìm kiếm các diễn viên bằng trình soạn thảo hoặc trình xử lý văn bản thông thường. Điều này gần như vô hình của các diễn viên kiểu C đặc biệt đáng tiếc vì chúng rất có khả năng gây tổn hại. Một hoạt động xấu xí nên có một hình thức cú pháp xấu xí. Quan sát đó là một phần lý do của việc chọn cú pháp cho các kiểu phôi mới. Một lý do nữa là các phôi kiểu mới khớp với ký hiệu mẫu, để các lập trình viên có thể viết các phôi của riêng họ, đặc biệt là các phôi được kiểm tra thời gian chạy.

Có lẽ, vì static_cast quá xấu và quá khó để nhập, bạn có nhiều khả năng suy nghĩ hai lần trước khi sử dụng một? Điều đó sẽ tốt, bởi vì các diễn viên thực sự hầu như có thể tránh được trong C ++ hiện đại.

Nguồn: Bjarne Stroustrup (người tạo C ++)


2
Tôi sẽ đánh giá thấp điều này nếu tôi có thêm một vài điểm, nhưng tiếc là tôi không thể. phôi kiểu c KHÔNG tương đương với reinterpret_cast. Hãy xem xét reinterpret_cast<int>(double);. Hoàn toàn có thể truyền một cú đúp thành int với kiểu cast c, nhưng không thể thực hiện được với reinterpret_cast. Tôi thấy Timbo đã chỉ ra điều này cho bạn và bạn nói rằng bạn sẽ sửa nó, nhưng bốn năm sau nó vẫn không chính xác. Tôi vẫn sẽ đánh giá thấp bạn nếu điều đó đã được khắc phục, vì có những lý do hoàn toàn hợp lệ để sử dụng diễn viên. Đây là một câu trả lời tốt hơn: stackoverflow.com/a/332086/3878168
Yay295

36

Các diễn viên C ++ bị hạn chế hơn (vì vậy hãy thể hiện ý định của bạn tốt hơn và làm cho việc xem lại mã dễ dàng hơn, v.v.). Chúng cũng dễ dàng hơn để tìm kiếm, nếu bạn cần.


10
... Và họ có nhiều khả năng làm những gì bạn dự định. ;-)
Macke

7
Và chúng còn rất nhiều thứ để gõ, cho bạn thêm một lý do để chỉ cần loại của bạn chính xác mà không cần phôi.
Michael Kohne

7
Và chúng xấu như một tính năng, làm cho rõ ràng trong đó trong mã có thể có các điểm cải tiến hoặc các trường hợp đặc biệt có thể yêu cầu tài liệu. - chỉnh sửa: wow tôi mới phát hiện ra tôi cũng đã trả lời câu hỏi này! XD
Klaim

Bây giờ tại sao tôi muốn tìm kiếm chúng?
Ded repeatator

@Ded repeatator Có rất nhiều lý do bạn có thể muốn biết nơi diễn ra diễn ra trong một cơ sở mã. Ví dụ: khi săn các lỗi có thể liên quan đến việc truyền (đặc biệt là khi thực hiện phát triển đa nền tảng).
Klaim

13

Tùy chọn C: dàn diễn viên "C ++ - style", vì nó không thể phân biệt được với một công trình:

int anInt = int(aFloat);

hoặc thậm chí:

int anInt(aFloat);

Điều đó sang một bên, ngoài những trường hợp tầm thường với các nguyên thủy, được hiểu rõ, tôi thích sử dụng x_cast <> s hơn các kiểu phôi C. Có ba lý do tại sao:

  • Họ định nghĩa hẹp hơn hoạt động mà lập trình viên đang cố gắng thực hiện.

  • Họ có thể thực hiện các hành động mà phôi kiểu C không thể (đặc biệt là trong trường hợp của Dynamic_cast <>, có thể truyền chéo qua các nhánh của chuỗi đa thừa kế).

  • Họ xấu xí . Họ lớn tiếng tuyên bố rằng các lập trình viên đang làm việc chống lại hệ thống loại. Trong trường hợp này, đó là một điều tốt .


7

Nếu viết mã trong C sử dụng một C đúc. Nếu viết bằng C ++, hãy sử dụng diễn viên C ++.

Trong khi hầu hết các lần truyền đều phá vỡ sự an toàn của loại phù hợp, thì các C ++ lại bị hạn chế nhiều hơn và do đó, bạn sẽ không an toàn hơn một chút so với việc sử dụng một nhóm C.

Tôi có thể chịu đựng được ai đó bằng cách sử dụng (T *) NULL mặc dù để buộc quá tải ...


7

Tôi có một vài quy tắc về các kiểu phôi C / C ++:

  1. Không áp dụng một const phải luôn luôn sử dụng a const_cast. Vì lý do rõ ràng. Đáng buồn thay, quy tắc của tôi về việc không áp dụng một const khiến bàn phím vươn lên và phá vỡ ngón tay của lập trình viên đã không được chấp thuận.
  2. Bất kỳ shenanigans kiểu thao tác bit nào mà các lập trình viên có được khi sử dụng kim loại đều nên sử dụng reinterpret_cast. Đây thực sự là loại diễn viên mà C không có: giả vờ các bit của số nguyên này thực sự là các bit của float. Điều này tránh sự khó chịu như thế nào (int)(*(int*)(&floatVar)).
  3. Nếu bạn gõ từ " dynamic_cast", hãy dừng lại và đánh giá lại hệ thống phân cấp và thiết kế lớp đa hình của bạn. Tiếp tục đánh giá lại thiết kế phân cấp lớp của bạn cho đến khi bạn có thể xóa những từ đó.
  4. Đừng bận tâm với static_cast.

Lý do đằng sau # 4 chỉ đơn giản là nó không quan trọng. Các trường hợp không phù hợp với các quy tắc khác là rõ ràng hoặc thực sự ở mức độ thấp. Một chuyển đổi được hiểu rõ về các loại đơn giản như int-to-float không cần cú pháp đặc biệt. Và nếu bạn đang chìm đắm trong sâu thẳm, xấu xí của một thứ gì đó, thì, bạn đang chìm trong ruột sâu, xấu xí của một thứ gì đó. Không cần phải chú ý đến thực tế rằng "ở đây có rồng", vì răng, móng vuốt và lửa đã cho đi rất nhiều.


1
dynamic_castlà một công cụ hoàn toàn hợp lệ. Hiếm khi hữu ích, tôi sẽ thừa nhận, nhưng nó khác xa với Satan của những thứ như các biến toàn cầu. Tuy nhiên, chủ yếu, tôi đánh giá thấp bạn vì bạn không trả lời câu hỏi , đó là về việc sử dụng hay không sử dụng phôi kiểu C.
DeadMG

2
@DeadMG: Tôi đã nói về dàn diễn viên kiểu C. Toàn bộ đoạn cuối biện minh cho các kiểu kiểu C có lợi cho static_cast.
Nicol Bolas

"Đáng buồn thay, quy tắc của tôi về việc không áp dụng một const khiến bàn phím vươn lên và phá vỡ ngón tay của lập trình viên đã không được chấp thuận." Về mặt kỹ thuật, nó thực sự hợp pháp cho trình biên dịch để thực hiện điều đó. Như là hợp pháp cho trình biên dịch để làm cho quỷ bay ra khỏi mũi của bạn .
Pharap


3

Nó thực sự phụ thuộc vào ngôn ngữ mà tôi đang làm việc với, vì bạn biết họ nói gì: Ở Rome nói tiếng La Mã. Vì vậy, nếu tôi lập trình bằng C, tôi cố gắng sử dụng các tính năng C ở mức tối đa, nhưng nếu tôi lập trình ở C ++, tôi sẽ tiếp tục và sử dụng các tính năng C ++ ở mức tối đa, ngay cả khi một số người không thích cách tiếp cận đó vì họ nói rằng nó làm cho mã "ít di động hơn", tôi nói rằng tôi không quan tâm, tôi đang ở C ++ và lập trình trong C ++ và tôi cần một trình biên dịch tương thích hoàn toàn với C ++ để biên dịch mã, nếu không tôi sẽ làm việc với một cái gì đó khác ở nơi đầu tiên


Nó không thực sự hoạt động khi cố gắng sử dụng các kiểu phôi C ++ trong C ;-)
Steve314

3

static_cast vv được phát minh vì các vấn đề với phôi kiểu C khi được sử dụng trong các mẫu. Nếu bạn đang viết một mẫu hoặc nếu mã của bạn sau này có thể được chuyển đổi thành một mẫu, thì nên sử dụng các kiểu phôi C ++. Lý do là bởi vì kiểu phôi C ++ thể hiện ý định tốt hơn, vì vậy họ sẽ đưa ra kết quả mong đợi trong trường hợp phôi kiểu C sẽ làm sai (đưa ra các loại cụ thể làm tham số mẫu).

Ngoài ra, tôi nói rằng hãy sử dụng các kiểu kiểu C ++ nếu bạn có một vấn đề cụ thể cần chúng - Dynamic_cast là phổ biến nhất, nhưng thậm chí đó có lẽ không phải là chuyện thường ngày.

Bất cứ điều gì khác, và một dàn diễn viên theo phong cách C có thể ít lộn xộn hơn và giúp dễ đọc hơn, hoặc có thể không phụ thuộc vào mức độ quen thuộc của người đọc với phong cách diễn viên ngày nay. Nó không thực sự quan trọng trong quan điểm của tôi, chủ yếu là một sở thích cá nhân, mặc dù đừng ngạc nhiên nếu một số người không thích phong cách C.

Lưu ý cuối cùng - nếu bạn cần quá nhiều diễn viên đến mức đây là một vấn đề lớn, có lẽ bạn đã làm sai điều gì đó. Có một số trường hợp ngoại lệ trong một số trường hợp, nhưng hầu hết các mã cấp cao không cần nhiều phôi (nếu có).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.