2011-10-10 35 views
13

Một vài ngày trước, tôi đã xem đoạn mã C++ này, mặc dù tôi không thể dán mã, tôi có thể tạo lại vấn đề với một số mã mẫu. Thứ nhất, tập tin, namespace.h:Tại sao sử dụng "C" bên ngoài xung quanh một không gian tên C++

#include <iostream> 
using namespace std; 

namespace useless{ 
    class X { 
    int m_myint; 
    static X *m_foobar; 
    X* getPrivVal(void); 
    public: 
    int getMember(void); 
    X* getStaticVal(void); 
    }; 
} 

Tiếp theo, namespace.cpp:

#include "namespace.h" 

extern "C"{ 
    namespace useless{ 
    X* X::m_foobar = NULL; 
    X* X::getPrivVal(void){ 
     if(m_foobar == NULL) 
      m_foobar = new X; 
     return(m_foobar); 
    } 
    } 
} 

namespace useless { 
    int X::getMember(void){ 
     if(m_myint == 0) 
      m_myint = 1; 
     return(m_myint); 
    } 
    X* X::getStaticVal(void){ 
     return(getPrivVal()); 
    } 
} 

using namespace useless; 

int main(void){ 
    X y; 
    cout << "The int value is " << y.getMember() << endl; 
    cout << "The value of the static member is " << y.getStaticVal() << endl; 
    return(0); 
} 

Mã này được biên soạn và được liên kết tốt khi tôi đã sử dụng g ++ 3.4.3, nhưng cung cấp cho các lỗi sau khi tôi sử dụng g ++ 4.x, tôi đã thử với GCC 4.6.1 cũng như GCC 4.2.1. Đã thử nó trên Linux cũng như Mac, cùng một kết quả.

Đây là lỗi (Suse):

g++ -o namespace namespace.cpp 
namespace.h:8:15: error: previous declaration of useless::X* 
    useless::X::m_foobar with C++ linkage 
namespace.cpp:5:11: error: conflicts with new declaration with C linkage 

Ai đó có thể xin làm sáng tỏ về C++ mã di sản gì đang tìm kiếm để làm, có thể này đã được một hack hoặc workaround để có được xung quanh một vấn đề cũ rằng tôi không biết nữa. Ohh bằng cách này, phương pháp bên trong các extern "C" được gọi bằng mã C + + và không phải bất kỳ mã C như tôi ban đầu nghi ngờ. FYI, đây là mã kế thừa bây giờ, có thể đã được viết vào giai đoạn 2001/2002.


Xin cảm ơn các bạn. Tôi đã đi trước và thoát khỏi "C" bên ngoài mà không có tác động lớn. @Bjorn Pollex: Người đã viết mã đó đã biến mất.

+6

Nếu mã này được kiểm soát phiên bản, hãy kiểm tra lịch sử để tìm ai đã viết và nhấn chúng bằng gậy cho đến khi họ ăn năn tội lỗi của họ. –

Trả lời

6

Có vẻ như một nỗ lực để tạo ra các biến witout C++ manglingling tên. Đó là một phần của việc sử dụng extern "C".

Trình biên dịch mới hơn rõ ràng nhận ra rằng nó thực sự không hoạt động.

2

Nếu bạn có một đoạn mã C++ mà bạn muốn gọi từ một mô-đun được viết bằng ngôn ngữ khác (C, FORTRAN hoặc bất kỳ thứ gì), bạn muốn tắt tên xén mang tên C++.

Chỉnh sửa: Điều thực sự kỳ lạ là họ đã làm điều đó trên định nghĩa nhưng không được khai báo. Ngạc nhiên là nó đã từng biên soạn

+3

Tắt tên mangling không có ý nghĩa khi bạn nói về C++ - các tính năng độc quyền như các lớp và không gian tên. –

14

Chỉ thị extern "C" có hai hiệu ứng, nó vô hiệu hóa xén khi có thể và sử dụng quy ước gọi điện C. Trong trường hợp đặc biệt này, bởi vì có một không gian tên ở giữa, tên mangling không thể bị vô hiệu hóa, vì vậy nó có thể đã được thêm vào để buộc một quy ước gọi cụ thể.

Mã thực sự sai ở chỗ khai báo không bắt buộc extern "C" nhưng định nghĩa không đúng, điều đó không chính xác. Hãy xem xét rằng nếu trình biên dịch chỉ theo chỉ thị như được hiển thị, người gọi sẽ sử dụng quy ước đặt tên và gọi C++, trong khi hàm sẽ sử dụng biến thể C, nếu hai khác biệt kết quả sẽ là hành vi không xác định.

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