2010-04-06 23 views
5

Nền:Xử lý định nghĩa lại macro mà không sửa đổi các tệp .h ... Ngôn ngữ C/C++

Giả sử rằng tôi có hai tệp tiêu đề a.h và b.h.

a.h chứa:

#define VAR 1 

b.h chứa:

#define VAR 2 

Lưu ý: Tên của cả hai vĩ mô là như nhau. Giả sử tôi có một số tệp myFile.c bao gồm cả hai tệp tiêu đề, tức là a.h và b.h.

Khi tôi cố gắng truy cập VAR, tôi nhận được lỗi định nghĩa lại VAR.

Để giải quyết vấn đề này, tôi đã chèn câu lệnh #ifndef VAR vào cả tệp a.h và b.h để ngăn lỗi này. tập tin a.h trở thành

#ifndef VAR 
    #define VAR 1 
#endif 

tập tin b.h trở thành

#ifndef VAR 
    #define VAR 2 
#endif 

Lưu ý: Các file header có thể chứa nhiều macro, không chỉ là một vĩ mô.

Sự cố:

Giả sử rằng tệp a.h và b.h được lấy từ thư viện của bên thứ ba. Các tệp này không chứa câu lệnh #ifndef VAR.

Tôi không được phép thay đổi tệp tiêu đề của họ.

Tôi có thể giải quyết lỗi định nghĩa lại 'VAR' macro trong tệp myFile.c hoặc myFile.cpp sử dụng macro VAR không?

Tôi biết tôi #undef VAR có thể được sử dụng để xác định VAR macro. Làm thế nào tôi có thể chọn lọc bao gồm VAR sau này trong chương trình của tôi? tức là trên dòng 10 của mã myFile.c tôi có thể tham khảo định nghĩa VAR từ tệp ah, trên dòng 15 của mã của tôi, tôi có thể tham khảo VAR từ tệp bh và trên dòng 18 một lần nữa tôi có thể tham khảo đến VAR từ tập tin ah.

Tóm lại, tôi có thể thực hiện đa hình macro không? Với tên của tệp tiêu đề, nó nên tham chiếu đến định nghĩa macro có trong tệp đó.

Tôi đã nghĩ đến việc sử dụng mẹo không gian tên để giải quyết vấn đề. Xác định tập tin tiêu đề đầu tiên trong không gian tên tập tin đầu tiên và thứ hai trong không gian tên thứ hai.

Tôi đã thử xác định hai không gian tên. Không gian tên đầu tiên chứa #include a.h và không gian tên thứ hai chứa b.h. Tuy nhiên, thủ thuật không gian tên không hoạt động với macro. Khi tôi cố gắng truy cập firstns :: VAR, trình biên dịch báo cáo một thông báo lỗi.

Bạn có thể đề xuất một số cách không?

Trả lời

4

Bạn có thể bao gồm các tệp tiêu đề có vấn đề luôn qua các tệp tiêu đề chuyên dụng của riêng bạn, nơi bạn có thể thêm các macro #ifdef, #undef cần thiết để ngăn lỗi định nghĩa lại. Ví dụ.

wrapperToA.h 
----- 
#ifdef VAR 
    #undef VAR 
#endif 

#include "a.h" 

Cập nhật: @Vlad làm việc ra các giải pháp đầy đủ trong khi chờ đợi - thanh danh cho anh ta (và +1 :-)

+0

này không không trả lời OP eed để thay thế lẫn nhau sử dụng định nghĩa '' hoặc 'B' của' VAR'. – vladr

7

mở rộng vĩ mô xảy ra ở cấp preprocessor và không thấm vào không gian tên sử dụng.

Tất cả các macro bạn muốn sử dụng hằng số đơn giản, không được sử dụng trong token concatenation, v.v ...?

Nếu vậy, thì bạn có thể thử một cái gì đó như sau để thu hẹp khoảng Preprocessor/biên dịch khoảng cách và giữ lại quyền truy cập vào cả AB định nghĩa về VAR vv, nếu nó phù hợp với tình hình của bạn:

// ab_wrapper.h 
#include <a.h> 
static const int A_VAR1 = VAR1; 
static const char* A_VAR2 = VAR2; 
#undef VAR1 
#undef VAR2 

#include <b.h> 
static const int B_VAR1 = VAR1; 
static const char* B_VAR2 = VAR2; 

// code.c 
#include <ab_wrapper.h> 
... 
int x = A_VAR1; 
int y = B_VAR1; 
... 
+0

Nó hoạt động cho các macro xác định hằng số. Phải làm gì cho các macro tính toán một số giá trị? Chúng ta có thể viết các hàm nội tuyến cho các macro như vậy và sau đó undef các macro đó không? – user310119

+0

@ user310119, vâng, chính xác. – vladr

0

Để mở rộng câu trả lời của Peter Torok.

Nói chung, nên bao gồm các thành phần của bên thứ 3.

Có nhiều bước sau:

  • gói các tiêu đề trong tiêu đề của riêng bạn, cho phép kiểm soát tùy chọn (ví dụ xác định một số thẻ tiền xử lý hoặc undefining người khác dựa trên mã thông báo riêng của bạn)
  • tạo ra một trọng lượng nhẹ thư viện mặt tiền cẩn thận để ẩn các phương thức nguy hiểm tiềm tàng, bọc chúng với các mutex nếu cần thiết ... và nếu không, chỉ cần ẩn các chi tiết để mọi thay đổi không gợn trong toàn bộ cơ sở mã của bạn.

Bạn quan tâm nhiều hơn đến câu lệnh đầu tiên, cũng là câu lệnh phổ biến nhất. Chỉ cần bọc chúng:

// wrapper/a.h 
#ifdef VAR 
#undef VAR 
#endif // ifdef VAR 

#include <3rdparty/a.h> 

Nếu bạn có hệ thống quấn tất cả phụ thuộc bạn theo cách này, bạn sẽ không có bất kỳ vấn đề tinh chỉnh sau đó vì bạn có thể thay đổi tiêu đề wrapper của riêng bạn và chỉ cần biên dịch lại các ứng dụng mà không cần can thiệp một cách rõ ràng trong bên thứ 3 tiêu đề (không bao giờ được khuyến nghị).

Tuy nhiên có một vấn đề về hiệu ứng mà bạn nên cẩn thận xem xét ...

// 3rdparty/a.h 
#define VAR 1 

// 3rdparty/aa.h 
#include "a.h" 
typedef int IntArray[VAR]; 

// 3rdparty2/b.h 
#define VAR 2 

này chắc chắn là phức tạp hơn :) Bạn cũng cần phải quấn "aa.h" với undef để tránh vấn đề này ...

Và tất nhiên, nó có nghĩa là bạn muốn tốt hơn không dựa vào VAR mình bất cứ nơi nào trong mã của bạn kể từ khi bạn biết định nghĩa của nó có thể thay đổi tùy thuộc thứ tự mà bạn bao gồm các tiêu đề ...

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