2009-06-03 43 views
47

Tôi đang gặp sự cố với khả năng hiển thị enum trong chương trình Mục tiêu-C. Tôi có hai tệp tiêu đề và một tệp định nghĩa một typedef enum. Một tệp khác cần sử dụng loại typedef 'd.Chuyển tiếp khai báo enum trong Mục tiêu-C

Trong C thẳng, tôi chỉ đơn giản là #include tệp tiêu đề khác, nhưng trong Mục tiêu-C, bạn không nên sử dụng #import giữa các tệp tiêu đề thay vì sử dụng các khai báo @class về phía trước nếu cần. Tuy nhiên, tôi không thể tìm ra cách để chuyển tiếp một kiểu liệt kê.

Tôi không cần giá trị được liệt kê thực tế, ngoại trừ trong tệp triển khai .m tương ứng, nơi tôi có thể an toàn #import. Vì vậy, làm thế nào tôi có thể nhận được typedef enum để được công nhận trong tiêu đề?

+0

Đối với câu trả lời gần đây (Swift 3, 2017) tìm kiếm tại câu trả lời của tôi. http://stackoverflow.com/a/42009056/342794 – lal

Trả lời

18

Hãy tiếp tục và sử dụng #import. Lý do duy nhất mọi người khuyên bạn nên sử dụng @class khi có thể là vì nó làm cho mã của bạn nhanh hơn một chút để biên dịch. Tuy nhiên, không có vấn đề với #import nhập một tệp .h từ tệp khác. Trong thực tế, bạn cần phải làm điều này khi mở rộng một lớp khác.

+1

Có cách nào ở trên là có thể, mà không cần sử dụng #import? Điều gì đơn giản là làm một 'typedef int EnumName'? –

+1

Tôi không nghĩ vậy. Xem các liên kết trong câu trả lời của gs: http://stackoverflow.com/questions/71416/forward-declaring-an-enum-in-c –

+0

Với #import biên dịch cần phút, và có một số điều có dây anyway. –

0

Bạn vẫn phải hoặc là #import hoặc tạo một tệp tiêu đề riêng chứa chỉ typedef. Không nhập các tệp tiêu đề trong tiêu đề làm cho việc biên dịch nhanh hơn, nhưng không thay đổi bất kỳ thứ gì khác.

Why doesn't C++ support forward declaration of enums?

16

Câu trả lời cho câu hỏi của bạn là một trong hai đi trước và nhập khẩu các tập tin tiêu đề typedef hoặc sử dụng một loại chung chung như NSInteger thay vì kiểu enum.

Tuy nhiên, có nhiều lý do hơn để không nhập tệp tiêu đề thay vì tốc độ biên dịch.

Không nhập tệp tiêu đề cũng làm giảm khả năng truy cập vô ý của bạn vào các lớp không liên quan. Ví dụ: giả sử bạn có một lớp TrackFileChanges theo dõi hệ thống tệp để thay đổi một tệp cụ thể và bạn có một lớp CachedFile lưu trữ dữ liệu đã lưu trong bộ nhớ cache từ một tệp. Sau này có thể sử dụng một loại ivar riêng của TrackFileChanges *, nhưng để sử dụng CachedFile, đây chỉ đơn giản là một chi tiết thực hiện (lý tưởng, ivar sẽ được tạo tự động với một thuộc tính riêng bằng cách sử dụng thời gian chạy mới, nhưng điều đó là không thể nếu bạn ' tái sử dụng thời gian chạy cũ).

Vì vậy, khách hàng #import "CachedFile.h" có thể không cần hoặc muốn truy cập vào TrackFileChanges.h. Và nếu họ làm như vậy, họ nên làm rõ bằng cách tự mình nhập dữ liệu. Bằng cách sử dụng @class TrackFileChanges instea của #import "TrackFileChanges.h" trong CachedFile.h bạn cải thiện đóng gói. Tuy nhiên, tất cả những gì đã nói, không có gì sai khi nhập tệp tiêu đề từ tệp tiêu đề thứ hai nếu tiêu đề thứ hai muốn hiển thị tệp đầu tiên cho tất cả các ứng dụng khách. Ví dụ, các tệp tiêu đề khai báo các lớp cần phải được nhập trực tiếp trong các tệp tiêu đề con, và các tệp tiêu đề khai báo các giao thức có thể được nhập trực tiếp (mặc dù bạn có thể sử dụng @protocol ABC; để tránh điều này).

4

Nếu bạn là ok sử dụng phần mở rộng trình biên dịch, bạn có thể sử dụng lệnh này trong Clang:

enum Enum; 
typedef enum Enum Enum2; 

void f(Enum2); // ok. it sees this type's true name. 

enum Enum { 
    E_1 
}; 

// ok. now its declaration is visible and we can use it. 

void f(Enum2 e) { 

} 

Lưu ý: Nó sẽ kích hoạt một cảnh báo -Wpedantic.


Nếu bạn đang sử dụng C++ 11, bạn nên sử dụng enums của họ, an toàn để chuyển tiếp tuyên bố - ví dụ: enum class Enum:uint8_t; (không phải là phần mở rộng của trình biên dịch).

cách
+1

Bạn có thể đơn giản hóa câu trả lời này: 'typedef enum Enum Enum;' Sau đó, chỉ cần sử dụng Enum trong định nghĩa phương thức và khai báo của bạn. –

15

gần đây nhất (Swift 3; tháng 5 năm 2017) để chuyển tiếp khai báo enum (NS_ENUM/NS_OPTION) trong Objective-C là sử dụng như sau:

// Forward declaration for XYZCharacterType in other header say XYZCharacter.h 
typedef NS_ENUM(NSUInteger, XYZCharacterType); 


// Enum declaration header: "XYZEnumType.h" 
#ifndef XYZCharacterType_h 
#define XYZCharacterType_h 

typedef NS_ENUM(NSUInteger, XYZEnumType) { 
    XYZCharacterTypeNotSet, 
    XYZCharacterTypeAgent, 
    XYZCharacterTypeKiller, 
}; 

#endif /* XYZCharacterType_h */` 
+1

làm việc cho tôi nhanh chóng 3 – stringRay2014

+3

Ngày nay nên là câu trả lời được chấp nhận – citxx

+1

Tôi bắt đầu nhìn vào typedef NS_ENUM chỉ ngày hôm qua như một cách để dọn sạch mã Objective C cũ - và câu trả lời này làm việc cho tôi. – Greg

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