2012-03-08 33 views
5

Câu hỏi có chủ đề.Có thể xác định tại thời gian chạy là điểm trỏ đến lớp C++ hoặc tại lớp Objective-C?

Tôi muốn viết một số mẫu chức năng phổ biến cho các đối tượng xóa an toàn và tự hỏi là nó có thể sử dụng một cái gì đó như thế này:

template< class T > void SafeDelete(T*& pVal) 
{ 
    if(objc_is_cpp_object(pVal)){ 
     delete pVal; 
     pVal = NULL; 
    } 
    else 
     [pVal release] 
} 
+1

Tại sao bạn muốn sử dụng cùng một tên hàm cho các ngôn ngữ khác nhau? Tại sao bạn không thể phân biệt chúng bằng cách sử dụng một tên khác? – iammilind

+2

C++ 'delete' và Obj-C' release' có nghĩa là những điều khá khác nhau; conflating hai dường như là một ý tưởng có vấn đề tốt nhất. –

+0

Tôi nghĩ về tên gọi khác nhau trước tiên, tôi chỉ cảm thấy tò mò về nó có thể có cùng một câu hỏi cho cả hai ngôn ngữ. Và sau đó tôi nghĩ rằng nó có thể không phải là ý tưởng rất tốt mặc dù, nhưng vẫn feelt tò mò :-) Vì vậy, đây chủ yếu là câu hỏi lý thuyết. –

Trả lời

4

Như đã đề cập trong nhận xét, tôi khuyên bạn không nên trộn C++ delete và Objective-C release.
Chỉ cần cho quan điểm kỹ thuật, bạn có thể sử dụng sau đây SFINAE lừa runtime:

template<typename T> struct void_ { typedef void type; }; 

template<typename, typename = void> 
struct CppType { static const bool value = false; }; 
template<typename T> 
struct CppType<T, typename void_<int (T::*)>::type> { static const bool value = true; }; 

template< class T > 
void SafeDelete(T*& pVal) 
{ 
    if(CppType<T>::value || std::is_pod<T>::value) { // <----- 
    delete pVal; 
    pVal = 0; 
    } 
    else { 
    // [pVal release]; 
    } 
} 

Có thể, is_pod có sẵn trong C++ 11, thúc đẩy vv Nhưng thật dễ dàng để thực hiện.

+0

Bạn có thể giải thích ý nghĩa của "typename void_ :: type" không? Theo tôi hiểu ý tưởng là chuỗi này trong trường hợp đối tượng objc sẽ được thay thế bằng loại void và phiên bản chuyên biệt của mẫu sẽ trả về false; Nhưng không thể hiểu được điều này xảy ra như thế nào. Cảm ơn bạn. –

+0

@ andrey.s, cơ chế này được gọi là SFINAE. 'int (T :: *)' có nghĩa là con trỏ đến biến thành viên. Bây giờ, con trỏ tới thành viên chỉ có thể cho C++ 'class' hoặc' union' và không cho bất kỳ thực thể nào khác. Do đó, nếu một kiểu đã cho là kiểu C++ 'class' thì' CppType :: giá trị' sẽ là 'true' và bạn có thể thực hiện các tác vụ cụ thể của C++. – iammilind

+2

Thats thật tuyệt, cảm ơn! –

2

Objective-C con trỏ cũng giống như con trỏ C++: 4-to-8 các giá trị số nguyên từ trỏ đến các đối tượng khác nhau trong bộ nhớ. Trình biên dịch Objective-C hỗ trợ xuất các giá trị với nhiều định dạng, chẳng hạn như bố cục đối tượng C, C++ và Objective-C.

Vậy đó. Có thực sự không phải là nhiều hơn thế.

Bạn có thể cố gắng làm một cái gì đó hacky như tạo ra một lớp nơi một lĩnh vực luôn luôn chứa một giá trị kỳ diệu:

template <class T> 
class Magic { 
    private: 
     const char magic[] = 1234567; 
    public: 
     bool is_object() const { 
      return magic == 1234567; 
     } 
} 

sau đó bạn có thể kiểm tra nó như vậy:

bool is_cpp(void *ptr) { 
    return ((Magic*) ptr)->is_object(); 
} 

Nhưng được cảnh báo trước đó đây là cực kỳ hacky.

+0

Đề xuất của bạn đang sử dụng lớp "Magic" cơ bản cho tất cả các đối tượng cpp? –

+0

đó là ý tưởng chung. một lần nữa, đây không phải là thứ bạn muốn làm trong sản xuất, bởi vì không có giá trị nào đặc biệt ... – Alex

+0

Mục tiêu-C đi kèm với ma thuật này: tất cả các đối tượng con trỏ target-c đều thuộc kiểu 'struct objc_object', có định nghĩa (albiet private) idiomatically phải chứa một thành viên 'isa_t isa' ... trong khi tôi không biết về kiểm tra thời gian chạy, cá nhân tôi tìm thấy' objc_object :: isa' khá tốt, đủ cho SFINAE ví dụ 'objc :: traits :: is_object '; xem: http://git.io/vCsLa - Đọc thêm: http://unixjunkie.blogspot.de/2006/02/nil-and-nil.html cộng với nguồn thời gian chạy objc - http: //www.opensource. apple.com/source/objc4/objc4-647/runtime/objc-private.h – fish2000

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