Vì vậy, tôi đã chán ngày hôm nay, và quyết định gây rối với C++/Obj-C nội suy, và tôi tìm thấy một cách để tạo ra một thiết lập rất thú vị.Mục tiêu-C - Nhược điểm để kết nối với C++?
@protocol NSCPPObj <NSObject>
-(id) init;
-(id) initWithInt:(int) value;
-(int) somethingThatReturnsAValue;
-(void) doSomething;
@end
class NSCPPObj : objc_object {
public:
static Class cls();
int iVar;
NSCPPObj();
NSCPPObj(int);
int somethingThatReturnsAValue();
void doSomething();
};
Như bạn có thể thấy, giao diện khá đơn giản và dễ hiểu. Chúng ta tạo ra hai (gần như) các giao diện giống nhau, một cho một đối tượng C++ và một cho giao thức Obj-C.
Bây giờ, tôi tìm thấy một cách để thực hiện điều này, nhưng cú đúp cho mình, điều này trở nên xấu xí:
// NSCPPObj.mm
#import <objc/runtime.h>
#import <iostream>
#import "NSCPPObject.h"
Class NSCPPObj_class = nil;
__attribute__((constructor))
static void initialize()
{
NSCPPObj_class = objc_allocateClassPair([NSObject class], "NSCPPObj", 0);
class_addMethod(NSCPPObj_class->isa, @selector(alloc), imp_implementationWithBlock(^(id self) {
return class_createInstance(NSCPPObj_class, sizeof(struct NSCPPObj));
}), "@@:");
class_addMethod(NSCPPObj_class, @selector(init), imp_implementationWithBlock(^(id self) {
return self;
}), "@@:");
class_addMethod(NSCPPObj_class, @selector(initWithInt:), imp_implementationWithBlock(^(id self, int value) {
((struct NSCPPObj *) self)->iVar = value;
return self;
}), "@@:i");
class_addMethod(NSCPPObj_class, @selector(doSomething), imp_implementationWithBlock(^(id self) {
((struct NSCPPObj *) self)->doSomething();
}), "[email protected]:");
class_addMethod(NSCPPObj_class, @selector(somethingThatReturnsAValue), imp_implementationWithBlock(^(id self) {
return ((struct NSCPPObj *) self)->somethingThatReturnsAValue();
}), "[email protected]:");
objc_registerClassPair(NSCPPObj_class);
}
Class NSCPPObj::cls()
{
return NSCPPObj_class;
}
NSCPPObj::NSCPPObj()
{
this->isa = NSCPPObj_class;
[((id<NSCPPObj>) this) init];
}
NSCPPObj::NSCPPObj(int value)
{
this->isa = NSCPPObj_class;
[((id<NSCPPObj>) this) initWithInt:value];
}
void NSCPPObj::doSomething()
{
std::cout << "Value Is: " << [((id<NSCPPObj>) this) somethingThatReturnsAValue] << std::endl;
}
int NSCPPObj::somethingThatReturnsAValue()
{
return iVar;
}
tôi sẽ tóm tắt những gì điều này:
- Phân bổ một lớp Pair
- Thêm tất cả các phương thức lớp và ví dụ vào đối tượng
- Đăng ký lớp học Pair
Bây giờ, như bạn có thể thấy, đây không phải là rất linh hoạt, nhưng nó làm việc, và đó là một con đường hai chiều:
id<NSCPPObj> obj = [[NSCPPObj::cls() alloc] initWithInt:15];
[obj doSomething];
NSLog(@"%i", [obj somethingThatReturnsAValue]);
NSLog(@"%@", obj);
NSCPPObj *objAsCPP = (__bridge NSCPPObj *) obj;
objAsCPP->doSomething();
std::cout << objAsCPP->somethingThatReturnsAValue() << std::endl;
Bạn cũng có thể tạo ra các đối tượng bằng cách sử dụng new NSCPPObj(15)
, nhưng hãy nhớ xóa đi! Rõ ràng, điều này có thể hoạt động trong môi trường ARC hoặc không phải ARC, nhưng ARC yêu cầu thêm một vài phôi cầu nối.
Vì vậy, tôi đến với câu hỏi thực tế:
Ưu điểm/nhược điểm của cấu trúc thiết kế này là gì? Tôi có thể liệt kê một vài tắt của đỉnh đầu của tôi:
Ưu điểm:
- điều hành quá tải với C++
- phương pháp động ràng buộc với ObjC
- có thể được xây dựng trong hoặc C++ hay thời trang ObjC
Nhược điểm:
- Hard-to-đọc thực hiện
- Selectors & bindings phải được bổ sung cho mỗi C++ thực hiện bổ sung vào giao diện
- đối tượng Class không thể được tham chiếu trực tiếp
Vì vậy, sau khi tất cả những gì, bạn sẽ khuyên này cấu trúc thiết kế trong một ứng dụng? và tại sao.
Tôi biết quá ít C++ để cung cấp cho câu trả lời này tốt, nhưng tôi tự hỏi nếu câu trả lời cho điều này phụ thuộc vào chính xác loại ứng dụng bạn đang làm việc. Một trò chơi C++ hiện có đang được chuyển sang có thể tìm thấy điều này hữu ích hơn nhiều so với một ứng dụng tiện ích đơn giản ... và một lập trình viên C++ dày dạn có thể đánh giá cao hơn một người có định hướng Mục tiêu-C nhiều. – lxt
Bỏ phiếu để mở lại. Tôi hiểu làm thế nào điều này có thể là 'không xây dựng', nhưng đây là một trang web cộng đồng. Tôi nhận ra bạn là một người kiểm duyệt, nhưng nhìn thấy bạn là người duy nhất muốn điều này đóng lại. –
Tôi không phải là người kiểm duyệt và tôi đã gắn cờ câu hỏi này để xem xét. Nó là chủ đề. – mydogisbox