2011-07-15 77 views
5

Tôi sử dụng typedef cho hầu hết mọi thứ, kể cả hàm. Trong vài tuần qua, tôi đã bắt đầu mã C++ của chúng tôi để phù hợp nhất có thể với tiêu chuẩn ISO C++ 11, sử dụng tài liệu dự thảo cuối cùng (N3242) làm hướng dẫn.Nhiều khai báo hàm C++ với tham số mặc định

Như chúng ta đã biết, thỉnh thoảng có nhiều khai báo leo vào mã của chúng tôi thông qua các extern xuất hiện trong nhiều tệp hoặc typedef được lặp lại. Theo đoạn trích này từ phần 7.1.3, trang 145 của tài liệu trên, điều này sẽ vô hại:

3. In a given non-class scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers.

[ Example:

typedef struct s { /* ... */ } s; 
    typedef int I; 
    typedef int I; 
    typedef I I; 

— end example ]

Vì vậy, tôi đã viết một chương trình để kiểm tra điều này. Ở dạng đơn giản nhất của nó:

typedef int (fcntype)(int, int); 
extern fcntype fcn1; 

int fcn1(int x, int y) { return x + y; } 

int main(int argc, char ** argv) { return fcn1(2, 3); } 

Biên soạn sử dụng gcc với

-Wfatal-errors -Wswitch-default -Wswitch-enum -Wunused-parameter -Wfloat-equal -Wundef -c -Wstrict-null-sentinel -std=c++0x -pedantic -Wall -Wextra 

có, tất nhiên, không có vấn đề. Hãy khai thác hàm bị từ chối:

typedef int (fcntype)(int, int); 
extern fcntype fcn1; 
extern fcntype fcn1; // woops. probably from an #include ... 

int fcn1(int x, int y) { return x + y; } 

int main(int argc, char ** argv) { return fcn1(2, 3); } 

Theo tiêu chuẩn dự đoán, không có vấn đề gì. Hãy thực hiện thay đổi khác với bản gốc:

typedef int (fcntype)(int, int=0); // default param. 
extern fcntype fcn1; 

int fcn1(int x, int y) { return x + y; } 

int main(int argc, char ** argv) { return fcn1(2); } // use the default param 

Một lần nữa, không có vấn đề gì. vấn đề này được đưa ra về khi chúng ta có cả decl trùng lặp và các tham số defaulted như thế này:

typedef int (fcntype)(int, int=0); // default param. 
extern fcntype fcn1; 
extern fcntype fcn1; // FYI this is line 3 in the error message below. 

int fcn1(int x, int y) { return x + y; } 

int main(int argc, char ** argv) { return fcn1(2); } // use the default param 

Và gcc phàn nàn với

decltest.cpp:3: error: default argument given for parameter 2 of ‘int fcn1(int, int)’ 

Tất nhiên, tôi đang dọn dẹp mã cách nó phải được làm sạch, đó là để nói rằng tôi đang corralling các decls thành một, tổ chức tốt hơn tập tin. Nhưng đây có phải là một lỗi trong trình biên dịch hoặc một sự hiểu lầm của tôi về những gì một tham số mặc định "là"?

Trả lời

6

Thứ nhất, đối với cùng một khai báo hàm cùng loại, chỉ có tối đa một khai báo xác định đối số mặc định. Điều này là do §8.3.6 [dcl.fct.default]/4:

... A default argument shall not be redefined by a later declaration (not even to the same value). [ Example:

... 
void m() { 
    void f(int, int);  // has no defaults 
    f(4);     // error: wrong number of arguments 
    void f(int, int = 5); // OK 
    f(4);     // OK, calls f(4, 5); 
    void f(int, int = 5); // error: cannot redefine, even to same value 
} 
... 

end example ] ...

Ngoài ra, như @Sven nhận thấy, một cuộc tranh luận mặc định sẽ không xuất hiện trong một typedef, mặc dù g ++ không thể bắt nó ngay cả với -pedantic . Tôi nghĩ rằng clangVisual C++ từ chối điều này nhưng tôi chưa thử.

+2

Ngoài ra, chú thích cuối trang 101 (trên cùng một trang): "Điều này có nghĩa là đối số mặc định không thể xuất hiện, ví dụ, trong khai báo con trỏ tới hàm, tham chiếu đến hàm hoặc khai báo typedef." Vì vậy, tôi nghĩ rằng 'typedef int (fcntype) (int, int = 0);' nên tự nó đã không biên dịch. Hay tôi đang thiếu một cái gì đó? – Sven

+0

Ah, vâng. Cảm ơn bạn đặc biệt cho các tài liệu tham khảo trong tiêu chuẩn. Tôi đã nhấn mạnh nó. Thật thú vị khi những thứ này trỗi dậy trên bạn, đó là một lý lẽ tốt để đi qua mã một lần trong một thời gian để dọn dẹp mọi thứ. –

1

Trích dẫn chuẩn của bạn không áp dụng ở đây, vì bạn không khai báo typedef nhiều lần, nhưng sử dụng nó nhiều lần.

Đối số mặc định thực sự là một trường hợp phức tạp, chúng chỉ xuất hiện trong một khai báo (và hãy nhớ rằng định nghĩa tự nó được tính là khai báo, thậm chí đặt đối số mặc định trong cả khai báo chuyển tiếp và định nghĩa là lỗi).

0

này tạo ra các lỗi tương tự:

extern int fcn1(int, int=0); 
extern int fcn1(int, int=0); 

Vì vậy, nó không ngạc nhiên phiên bản typedef của bạn không hoạt động.

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