2010-04-26 39 views
40

Tôi đang cố gắng kết hợp Objective-C với C++. Khi tôi biên dịch mã, tôi nhận được một số lỗi.Trộn Objective-C và C++

A.h

#import <Cocoa/Cocoa.h> 
#include "B.h" 

@interface A : NSView { 
    B *b; 
} 

-(void) setB: (B *) theB; 

@end 

giờ sáng

#import "A.h" 

@implementation A 

- (id)initWithFrame:(NSRect)frame { 
    self = [super initWithFrame:frame]; 
    if (self) { 
     // Initialization code here. 
    } 
    return self; 
} 

- (void)drawRect:(NSRect)dirtyRect { 
    // Drawing code here. 
} 

-(void) setB: (B *) theB { 
    b = theB; 
} 

@end 

B.h

#include <iostream> 

class B { 

    B() { 
     std::cout << "Hello from C++"; 
    } 

}; 

Sau đây là các lỗi:

/Users/helixed/Desktop/Example/B.h:1:0 /Users/helixed/Desktop/Example/B.h:1:20: error: iostream: No such file or directory 
/Users/helixed/Desktop/Example/B.h:3:0 /Users/helixed/Desktop/Example/B.h:3: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'B' 
/Users/helixed/Desktop/Example/A.h:5:0 /Users/helixed/Desktop/Example/A.h:5: error: expected specifier-qualifier-list before 'B' 
/Users/helixed/Desktop/Example/A.h:8:0 /Users/helixed/Desktop/Example/A.h:8: error: expected ')' before 'B' 
/Users/helixed/Desktop/Example/A.m:26:0 /Users/helixed/Desktop/Example/A.m:26: error: expected ')' before 'B' 
/Users/helixed/Desktop/Example/A.m:27:0 /Users/helixed/Desktop/Example/A.m:27: error: 'b' undeclared (first use in this function) 
+2

Đừng quên rằng bạn buộc người dùng của lớp ObjC của bạn để sử dụng ObjC++ nếu bạn đặt C++ bao gồm trong tiêu đề - sử dụng con trỏ đục để tránh điều đó. –

+0

@gf Vì vậy, bạn sẽ khuyên bạn nên làm điều này như thế nào? Tôi có nên sử dụng một con trỏ void, hoặc tôi có thể sử dụng một loại id? – LandonSchropp

+1

Để tránh mất an toàn loại cá nhân tôi thích các cấu trúc được khai báo trước (http://stackoverflow.com/questions/2262011/adding-c-object-to-objective-c-class/2262395) nhưng cũng đã thấy * "riêng tư" * Các lớp ObjC (tức là thông qua các biến mẫu 'id'). –

Trả lời

73

Bạn cần đặt tên cho số .m tệp .mm. Và bạn sẽ có thể biên dịch mã C++ với Objective-C.

Vì vậy, hãy làm theo ví dụ của bạn, tệp AView.m của bạn phải được đặt tên là AView.mm. Nó đơn giản như vậy. Nó hoạt động rất tốt. Tôi sử dụng rất nhiều container std (std :: vector, std :: queue, vv) và mã C++ kế thừa trong các dự án iPhone mà không có bất kỳ biến chứng nào.

+0

Tôi không thể đổi tên tệp .m thành .mm do các lớp khác sẽ báo cáo lỗi nếu tôi sử dụng phần mở rộng .mm. Bất kỳ giải pháp khác là tâm trí? – Scar

5

Đừng bận tâm, tôi cảm thấy ngu ngốc. Tất cả những gì bạn phải làm là đổi tên AView.m thành AView.mm để trình biên dịch biết nó là Objective-C++, và nó biên dịch mà không có vấn đề gì.

+2

Tôi chỉ vui vì nó là đơn giản, vì bây giờ tôi có thể sử dụng mã của bạn như là một mẫu để cố gắng crap này ra bản thân mình! – Teekin

+1

Có một cách khác để làm điều đó - trong cửa sổ thuộc tính tệp (quên nó được gọi là gì - cửa sổ bên phải khi được nhấp vào một tệp trong Navigator), bạn có thể đặt loại tệp độc lập với phần mở rộng tệp của nó. –

2

bạn có thể giữ giao diện sạch hơn với tờ khai chuyển tiếp của các lớp học C++:

#import <AnObjCclass.h> 
class DBManager; // This is a C++ class. NOTE: not @class 

@interface AppDelegate : UIResponder <UIApplicationDelegate, 
            CLLocationManagerDelegate, 
            MFMailComposeViewControllerDelegate> 
{ 
    DBManager* db; 
... 
} 
+3

Điều này không trả lời được câu hỏi. Đó là về phong cách mã và không có gì để làm với các lỗi trình biên dịch báo cáo trong câu hỏi. Nó phải là một bình luận. –

0

Trong tình huống mà bạn muốn giới thiệu một hàm C++ đơn giản như std::cout << Licks sau đó nóng cung cấp một lựa chọn tốt.

Thay đổi "Identity and Type" From: Objective-C source Để: Objective-C++ source

Việc gia hạn .mm chỉ xác định các loại tập tin; và sau đó bạn đang tìm kiếm một Objective-C++ không phải là một kiểu Objective-C.

1

Tôi đang chia sẻ một số điểm mà tôi đã hiểu về chủ đề này.

Chúng tôi có thể kết hợp cả tệp .cpp và .m với giao diện C thuần túy. Như chúng ta biết trình biên dịch Clang sẽ hỗ trợ C++, Objective C cũng như Objective C++, nó có thể là một phương tiện tốt hơn để trộn các ngôn ngữ này.

Một điều khi trộn các ngôn ngữ này để được chăm sóc là sử dụng các tệp tiêu đề. Chúng ta có thể giữ C++ trong các tiêu đề C mục tiêu của chúng ta bằng cách khai báo các đối tượng Cpp trong các phần mở rộng của lớp.

Hoặc chúng ta có thể khai báo các đối tượng cpp ngay khi bắt đầu khối @implementation trong tệp Cpp (.mm) Mục tiêu của chúng ta.

Quản lý bộ nhớ sẽ là mối quan tâm khi chúng ta đang xử lý các đối tượng Cpp. Chúng tôi có thể phân bổ memmory cho một đối tượng bằng cách sử dụng ‘new’ và giải phóng bộ nhớ bằng cách gọi ‘delete object’. Thông thường nếu chúng ta đang sử dụng ARC, chúng ta không cần phải biết về việc giải phóng bộ nhớ cho một đối tượng.

Trong khi sử dụng các lớp cpp, chúng ta có thể khai báo một đối tượng Cpp theo hai cách nói trình bao bọc CppWrapper và trình bao bọc CppWrapper * trong đó CppWrapper là một lớp Cpp. Khi chúng tôi đang sử dụng sau này các lập trình viên chịu trách nhiệm quản lý các memmory. Một điều quan trọng nữa là khi chúng ta gọi phương thức C với các tham số, chúng ta chuyển các tham chiếu, trong khi trong cpp chúng ta cần truyền tham số bằng cách sử dụng từ khóa '&', nếu không thì sao chép đối tượng đã được thông qua.

Việc phân bổ đối tượng mục tiêu C được xử lý trong thời gian chạy, trong đó khi ‘xóa’ được gọi đến đối tượng Cpp, đối tượng Cpp sẽ không còn trong bộ nhớ.

Khi viết CPP, chúng tôi đã chia sẻ con trỏ và con trỏ yếu là giống với kẻ mạnh và yếu trong Objective C.

http://philjordan.eu/article/mixing-objective-c-c++-and-objective-c++ http://www.raywenderlich.com/62989/introduction-c-ios-developers-part-1