2009-06-29 27 views
5

Tôi cần phải trộn Objective-C và C++. Tôi muốn ẩn tất cả các công cụ C++ bên trong một lớp và giữ tất cả các đối tượng khác đồng bằng Objective-C. Vấn đề là tôi muốn có một số lớp C++ như các biến mẫu. Điều này có nghĩa là chúng phải được đề cập trong tệp tiêu đề, được bao gồm bởi các lớp khác và C++ bắt đầu lan rộng đến toàn bộ ứng dụng. Giải pháp tốt nhất mà tôi có thể thực hiện cho đến thời điểm này giống như sau:Các lớp C++ như các biến mẫu của một lớp Objective-C

#ifdef __cplusplus 
#import "cppheader.h" 
#endif 

@interface Foo : NSObject 
{ 
    id regularObjectiveCProperty; 
    #ifdef __cplusplus 
    CPPClass cppStuff; 
    #endif 
} 

@end 

Tác phẩm này. Các tập tin thực hiện có một mở rộng mm, do đó nó được biên dịch như Objective-C trộn với C++, các #ifdef mở khóa các công cụ C++ và có chúng tôi đi. Khi một số khác, hoàn toàn Objective-C lớp nhập khẩu tiêu đề, các công cụ C++ là ẩn và lớp học không thấy bất cứ điều gì đặc biệt. Điều này trông giống như một hack, là có một giải pháp tốt hơn?

+1

Đó là cơ bản những gì tôi đã đưa ra khi tôi đã có cùng một vấn đề. Nhưng chú ý đến ifdef của bạn: bạn phải chèn padding cho nhánh non-cpp. Nếu không trình biên dịch sẽ không biết kích thước của các đối tượng Foo của bạn. Mặc dù điều này có thể không phá vỡ các bản dựng var instance không mong manh, nhưng nó chắc chắn là một vấn đề cho các mục tiêu kiểu cũ. –

+0

Tôi đã sao chép phương pháp bạn đã nêu ở trên. Dường như khá tốt đẹp và dễ dàng, nhưng sau đó nó gây ra một số vấn đề tham nhũng bộ nhớ điên: http://stackoverflow.com/questions/2458652/objective-c-insanity-simple-assignement-to-a-single-float-variable-results – morgancodes

Trả lời

8

Điều này nghe giống như sử dụng cổ điển cho giao diện/giao thức @. Xác định một giao thức khách quan-c cho API và sau đó cung cấp một triển khai thực hiện giao thức đó bằng cách sử dụng lớp Objective-C++ của bạn. Bằng cách này, khách hàng chỉ cần biết về giao thức chứ không phải là tiêu đề của việc triển khai. Vì vậy, cho việc thực hiện ban đầu

@interface Foo : NSObject 
{ 
    id regularObjectiveCProperty; 
    CPPClass cppStuff; 

} 

@end 

tôi sẽ xác định một giao thức

//Extending the NSObject protocol gives the NSObject 
// protocol methods. If not all implementations are 
// descended from NSObject, skip this. 
@protocol IFoo <NSObject> 

// Foo methods here 
@end 

và sửa đổi các Foo khai ban đầu để

@interface Foo : NSObject <IFoo> 
{ 
    id regularObjectiveCProperty; 
    CPPClass cppStuff; 
} 

@end 

Khách hàng mã thì có thể làm việc với loại id<IFoo> và không cần được biên dịch như Objective-C++. Rõ ràng bạn có thể chuyển một phiên bản của Foo cho các khách hàng này.

+0

Nếu @interface Foo có trong tệp .h, nó có thể ngăn chặn ảnh hưởng của obj-C++? Nếu @interface Foo nằm trong tệp .mm, làm thế nào tôi có thể tạo một phiên bản của nó? – Eonil

+1

Bất kỳ mô-đun nào nhập Foo.h sẽ phải được biên dịch dưới dạng Mục tiêu-C++, nhưng mã máy khách chỉ cần nhập * * tiêu đề của IFoo để sử dụng IFoo và do đó chỉ có thể là Mục tiêu-C. Đây là một mô hình quản lý phụ thuộc cổ điển. –

+0

trong ví dụ của bạn, làm thế nào để tạo một Foo mới mà không cần nhập tiêu đề? Điều đầu tiên xuất hiện trong đầu là một lớp nhà máy C++ mục tiêu không nhập và các công cụ C++ vào tiêu đề của nó. Tất cả dường như rất phức tạp. Ngoài ra còn có cách tiếp cận này: http://stackoverflow.com/questions/2262011/adding-c-object-to-objective-c-class/2262395 nhưng tôi đã không nhận được nó để làm việc (xem http://stackoverflow.com/questions/2463970/trouble-using-opaque-pointers-in-objective-c) – morgancodes

1

Có một số lý do cụ thể mà bạn không thể chỉ sử dụng Objective C++ cho mọi thứ không? Đơn giản chỉ cần chuyển trình biên dịch sang Compile Sources As: Objective C++ (hoặc đổi tên tất cả các file nguồn của bạn từ .cpp hoặc .m thành .mm). Sau đó, bạn có thể tự do intermix C++ và Objective C.

C++ bắt đầu lây lan sang toàn bộ ứng dụng

vấn đề gì là có với điều đó? Nếu mã Objective C của bạn chỉ làm việc với mã C/Objective C nói chung, thì nó gần như chắc chắn sẽ không bị ảnh hưởng gì cả khi được biên dịch thành C++. Không có vấn đề về kích thước hoặc hiệu suất tốc độ đáng kể.

Chỉ có hai nhược điểm mà tôi đã tìm thấy là: bạn không thể (chưa) sử dụng phân tích tĩnh tĩnh để phân tích C++; một số mã C (tương đối kỳ lạ) sẽ không hoạt động trong C++, đôi khi là một vấn đề khi sử dụng mã C của bên thứ ba.

+0

Vấn đề duy nhất là tôi không thoải mái với C++ và tôi sợ sẽ có một số khác biệt tinh tế có thể dẫn đến lỗi. Tôi thích ý tưởng của C++ được đóng gói chỉ trong lớp mà thực sự cần nó. Nhưng cảm ơn bạn, điều này chắc chắn là một giải pháp. – zoul

0

Bạn có thể thấy rằng bạn gặp sự cố khi thực hiện điều này - từ những gì tôi nhớ về ObjectiveC++, bạn có thể thấy rằng hàm tạo và hàm hủy cho đối tượng C++ kèm theo của bạn sẽ không được gọi.

3

Gần đây tôi cũng gặp sự cố này. Trong trường hợp của tôi một giao thức là quá mức cần thiết. Tôi chỉ cần giữ một con trỏ đến một đối tượng truy cập dữ liệu đã xảy ra là một đối tượng C++.

Điều tôi đã làm là khai báo lớp với biến ví dụ void * và bỏ nó khi tôi sử dụng nó trong các phương thức thể hiện.

Đây là một chút hack-y, nhưng về mặt khái niệm, nó rất giống với loại Objective-C id.

0

KHÔNG DO

NÀY Nếu bạn ifdef ra một biến Ví dụ, mà sẽ cung cấp hai ví dụ bố trí biến riêng cho lớp này. Bạn sẽ nhận được các bộ nhớ ngẫu nhiên trên khắp nơi vì bộ nhớ được phân bổ cho đối tượng trong một nửa các trường hợp sẽ quá ngắn. Thay vì ifdefing ra biến Ví dụ, chuyển tiếp-tuyên bố loại của nó như

struct CPPClass; 

và có một con trỏ đến nó trong Ivar, sau đó trong init/dealloc bạn phương pháp gọi mới/xóa để tạo ra các đối tượng. Nếu bạn có một số đối tượng, bạn có thể tạo một cấu trúc để giữ tất cả các mã vạch C++ trực tiếp và sau đó chỉ mới/xóa cấu trúc đó.

Xem chủ đề này cho biết thêm chi tiết và liên kết hơn nữa để thông tin, bao gồm một podcast mà nói dài về ObjC++: Can I separate C++ main function and classes from Objective-C and/or C routines at compile and link?

+0

Trong C, một kiểu cấu trúc sẽ phải được gọi là 'struct CPPClass', không phải' CPPClass', vì vậy chúng sẽ phải thay đổi điều đó. – newacct

+0

Trong khai báo ivar, vâng, bắt tốt. Để C++ struct Foo và Foo là như nhau mặc dù, vì vậy nó chỉ cần thiết trong tiêu đề. Thông thường tôi chỉ viết cấu trúc trước tên lớp ở khắp mọi nơi tôi sử dụng nó, bạn không cần một tuyên bố cấu trúc riêng biệt như tôi đã đề cập ở đây một mình. – uliwitness

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