2011-07-06 32 views
7

Với C++ định nghĩa sau đây:Tại sao tôi không thể gán phần tử enum sai, nhưng có thể so sánh với phần tử enum sai?

enum EnumA { 
    EA_Element = 1 
}; 

enum EnumB { 
    EB_Element = 10 
}; 

đoạn mã sau sẽ không biên dịch và rằng chỉ có ý nghĩa:

EnumA variable; 
variable = EB_Element; // won't compile 

nhưng mã sau đây không biên dịch:

EnumA variable = EA_Element; 
if(variable == EB_Element) { //will compile 
} 

mặc dù nó không thể làm cho bất kỳ ý nghĩa - enums khác nhau được so sánh và mã như vậy có khả năng sai lầm.

Tại sao các tình huống có vẻ giống hệt này được xử lý khác trong C++?

+2

không nên là trường hợp không biên dịch sẽ là: 'variable = EB_Element;'? – Donotalo

+0

@Donotalo: Đã sửa lỗi, cảm ơn bạn. – sharptooth

Trả lời

4

Đối số đó là chính xác như, tôi đã thấy rằng mọi loại enum có thể được so sánh với bất kỳ loại nào enum. Đó là vì mục đích so sánh, enum biến và giá trị phải là được chuyển đổi thành loại tích phân (chẳng hạn như int). Trình biên dịch nhất định thực hiện raise the warning.

Đối số như vậy có thể giữ đúng để so sánh giữa unsigned int, int, size_t v.v ... nhưng có thể tất cả chúng đều bị giới hạn trong cảnh báo trình biên dịch vì lý do tương tự.

Tuy nhiên, sự cố này được giải quyết trong C++ 0x với enum class (chúng chưa thay đổi hoạt động enum hiện có để duy trì khả năng tương thích).

2

Nó không phải là không thể của nó, nó chỉ là trình biên dịch của bạn coi chúng là hai loại dữ liệu khác nhau khi chúng vừa là số nguyên. Vì vậy, một typecast đơn giản sẽ giải quyết vấn đề.

EnumA variable; 
variable = (EnumA)EB_Element; 
+1

diễn viên là không cần thiết. – Donotalo

+0

Tôi không hiểu tại sao không. – Drake

+0

nhận xét của tôi trước khi chỉnh sửa. – Donotalo

6

Nó sẽ biên dịch vì "Theo enums mặc định được chuyển thành số nguyên cho phép toán số học." (In: Ngôn ngữ lập trình C++)

1

Chào mừng bạn đến với C++!

cho một cái gì đó thậm chí hài hước thử điều này:

#include <string> 

int main(int argc, const char *argv[]) 
{ 
    std::string s; 
    s = 3.141592654; 
    return 0; 
} 

tại sao nó biên dịch? Lý do là các quy tắc ngôn ngữ nói như vậy.

Trong trường hợp sôi nổi này giải thích "chính thức" về lý do tại sao ví dụ này biên dịch là dường như cho phép std::string::operator+=(char) (IMO ok và logic từ quan điểm thực dụng) và "do đó" cũng được gán từ char (IMO illogical non) - hậu quả). Nhưng ký tự là ints (phi logic, nhưng di sản C) và đôi có thể được chuyển đổi hoàn toàn thành int (phi logic, nhưng di sản C). Vì vậy, trong C++ nó vô lý (nhưng hợp pháp) để gán một đôi vào một chuỗi. Không cảm thấy xấu nếu bạn không biết, hầu hết các lập trình viên C++ tôi cho thấy điều này thật khó hiểu vì sao một trình biên dịch vô nghĩa như thế và nghĩ về một trong hai lỗi ngữ nghĩa hoặc trình biên dịch khác.

Trong trường hợp của câu hỏi của bạn, lý do là enums giống như ints trong một số ngữ cảnh (có thể do di sản trong trường hợp sử dụng) nhưng không giống như ints trong một số ngữ cảnh khác. Đó là vô lý nhưng đó là những gì các tiêu chuẩn bắt buộc.

Nếu bạn cảm thấy không thoải mái với điều này dường như không có logic, hãy nhớ rằng C++ chủ yếu là kết quả của một lịch sử lâu dài và thậm chí cả một ủy ban (!). Điều này cũng ngụ ý rằng người ta không thể sử dụng logic để tránh học C++: dù bạn có thông minh đến đâu đi chăng nữa thì không có cách nào bạn có thể đoán được các tai nạn lịch sử và quyết định chính trị của ủy ban.

Độ phức tạp cao của C++, sự vắng mặt của logic ở nhiều nơi và sự hiện diện của undefined behavior daemons thay vì runtime error angels cũng là những gì IMO về cơ bản quyết định học C++ bằng thử nghiệm.

Chọn một cuốn sách hay (hoặc một số ít) và đọc nó (chúng) che phủ để che đi ... không may là không có cách nào khác. Đề xuất của tôi là: "Ngôn ngữ lập trình C++" (Stroustrup), "Hiệu quả C++" & "Hiệu quả hơn C++" (Meyers), "C++ Câu hỏi thường gặp" (Cline/Lomow/Girou).

C++ là một vũ khí khá mạnh mẽ và tốt đẹp để sở hữu, nhưng tiếp cận nó từ phía bên trái và nó chỉ có thể trở thành tồi tệ nhất của cơn ác mộng của bạn. Giả sử rằng bạn có thể hiểu nó chỉ bằng cách sử dụng logic là một cách tiếp cận sai (và không phải vì logic của bạn là yếu, nhưng vì C + + không chỉ là logic).

+0

-1, bạn đã không trả lời câu hỏi, ví dụ không có mang về câu hỏi, và logic có tất cả mọi thứ để làm với lý do tại sao mà ví dụ biên dịch. –

+0

Câu trả lời đã có sẵn cho cả hai trường hợp (vì tiêu chuẩn nói như vậy) và tôi nghĩ điều quan trọng là cảnh báo về sai lầm của việc đánh giá quá cao sức mạnh của logic khi hiểu C++. Tuy nhiên tôi đã thêm một lời giải thích chi tiết hơn nếu điều này làm cho bạn cảm thấy tốt hơn. Tôi thích C++ nhưng nếu bạn nói đó là một ngôn ngữ logic thì IMO bạn vẫn đang ở giai đoạn fanboy. Hãy quay lại sau khi viết vài trăm nghìn dòng mã C++ đang hoạt động và chúng ta hãy nói lại. – 6502

+0

Ồ, tôi đã viết nhiều hơn phần chia sẻ công bằng của mình về C++, và tôi không phải là một fanboy. Về 's = 3.14159; 'có nó xấu xí. Tuy nhiên, mỗi bước từ dấu phẩy động đến số nguyên thành char để gán là khá ổn. Bạn đồng ý 's + = some_char;' là OK. Lưu ý rằng 's + = some_char;' có cùng tác dụng như 's = some_char;' trong trường hợp của một chuỗi rỗng - vì vậy việc cung cấp 'toán tử = (char)' có ý nghĩa hoàn hảo. Ví dụ của bạn minh họa tại sao các tổ chức thực hiện đánh giá mã. Chỉ vì một đoạn mã hoàn toàn hợp lệ không có nghĩa là nó không ngửi thấy mùi trời cao. –

Các vấn đề liên quan