2015-02-12 21 views
6

tôi đang trải qua C++11 standard draft một thời gian trước và đã xem qua một này (trong §8.3.6, p 204).:C++ - Khai báo chức năng bên trong phạm vi chức năng?

void g(int = 0, ...); // OK, ellipsis is not a parameter so it can follow 

// a parameter with a default argument 
void f(int, int); 
void f(int, int = 7); 
void h() { 
    f(3); // OK, calls f(3, 7) 
    void f(int = 1, int); // error: does not use default 
    // from surrounding scope 
} 
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 
} 
void n() { 
    f(6); // OK, calls f(6, 7) 
} 

này đã phải làm với các đối số mặc định chức năng. Những gì tôi đột quỵ là một thực tế rằng các khai báo chức năng xuất hiện ở phạm vi chức năng. Tại sao vậy? Tính năng này được sử dụng để làm gì?

+0

Tôi đã sử dụng điều này để khai báo một hàm mà tôi biết sẽ chỉ được gọi trong phạm vi. – Atul

+0

Câu trả lời ngắn gọn là nó hiếm khi được sử dụng. Về lý thuyết, nó có thể hữu ích nếu (ví dụ) bạn có một biến và một hàm có cùng tên. Một khai báo ở một phạm vi bên trong sẽ ẩn một khai báo ở một phạm vi bên ngoài. –

Trả lời

5

Mặc dù tôi không biết bạn có thể làm điều này, tôi đã thử nghiệm và nó hoạt động. Tôi đoán bạn có thể sử dụng nó để chuyển tiếp các hàm được khai báo được xác định sau, như sau:

#include <iostream> 

void f() 
{ 
    void g(); // forward declaration 
    g(); 
} 

void g() 
{ 
    std::cout << "Hurray!" << std::endl; 
} 

int main() 
{ 
    f(); 
} 

Nếu bạn xóa khai báo trước, chương trình sẽ không biên dịch. Vì vậy, bằng cách này bạn có thể có một số loại tầm nhìn khai báo dựa trên phạm vi dựa trên.

+0

Hmm, OK, có thể trở nên hữu ích một thời gian! :) –

+2

@ HenriKorpela Tôi phải nói rằng tôi không bao giờ biết về điều này, và không nghĩ rằng tôi sẽ sử dụng một "tính năng" như vậy. Tôi rất muốn có thể ** định nghĩa ** các chức năng bên trong các hàm khác, mà không cần thủ thuật phổ biến của gói sau đó là 'static' bên trong một' struct/class'. – vsoftco

+0

Bạn đã bao giờ nghe nói về một phân tích vexing? Bạn có thể vô tình khai báo một hàm thay vì một cá thể. Mọi người thường nghĩ rằng 'Foo f();' khai báo và gọi hàm tạo mặc định cho 'f', nhưng nó khai báo một hàm thay thế. – 0x499602D2

0

Bất kỳ khai báo hàm/biến nào đều có khả năng hiển thị và phạm vi của nó. Ví dụ, nếu ở trong lớp, chỉ các thành viên lớp mới có thể nhìn thấy nó. Nếu trong chức năng chỉ có chức năng có thể có khả năng hiển thị với nó, sau khi chúng tôi khai báo biến hoặc chức năng.

Chúng tôi thường sử dụng cấu trúc dữ liệu trong phạm vi chức năng. Nhưng quy tắc ngữ pháp của trình biên dịch có thể áp dụng cho cả hai, vì hàm trong chính nó có địa chỉ và do đó khả năng hiển thị cũng có thể áp dụng cho nó.

+0

Nhưng bạn vẫn có thể gọi hàm từ bất kỳ hàm nào khác chức năng được xác định bên dưới nó, vì vậy bạn chỉ cần ẩn nó ở trên (bạn không thể ** xác định ** chức năng của bạn bên trong chức năng khác) – vsoftco

+0

Có phạm vi cơ bản của nó về. – Atul

+0

Đó là những gì tôi không nghĩ nó đúng. Nó không hoàn toàn về phạm vi, vì ngoài phạm vi vẫn có thể sử dụng hàm, vì bạn phải định nghĩa hàm ở phạm vi toàn cục (trừ các thành viên lớp học). Chỉ các hàm được khai báo ở trên nó không thể sử dụng nó. – vsoftco

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