2015-04-16 25 views
75

Ví dụ một tuyên bố như rằng:Tại sao C++ cho phép chúng ta bao quanh tên biến trong dấu ngoặc đơn khi khai báo một biến?

int (x) = 0; 

Hoặc thậm chí rằng:

int (((x))) = 0; 

tôi stumbled khi này vì trong mã của tôi, tôi đã xảy ra để có một đoạn tương tự như sau:

struct B 
{ 
}; 

struct C 
{ 
    C (B *) {} 
    void f() {}; 
}; 

int main() 
{ 
    B *y; 
    C (y); 
} 

Rõ ràng tôi muốn xây dựng đối tượng C mà sau đó sẽ làm điều gì đó hữu ích trong destructor của nó. Tuy nhiên khi nó xảy ra trình biên dịch xử lý C (y); như một tuyên bố của biến y với loại C và do đó nó in một lỗi về y định nghĩa lại. Điều thú vị là nếu tôi viết nó như là C (y).f() hoặc như một cái gì đó như C (static_cast<B*> (y)) nó sẽ biên dịch như dự định. Cách giải quyết hiện đại tốt nhất là sử dụng {} trong cuộc gọi hàm tạo, tất nhiên.

Vì vậy, như tôi đã tìm ra sau đó, có thể khai báo các biến như int (x) = 0; hoặc thậm chí int (((x))) = 0; nhưng tôi chưa bao giờ thấy bất kỳ ai thực sự sử dụng các khai báo như thế này. Vì vậy, tôi quan tâm-đó là mục đích của khả năng như vậy bởi vì bây giờ tôi thấy rằng nó chỉ tạo ra các trường hợp tương tự như "nổi tiếng nhất phân tích cú pháp" và không thêm bất cứ điều gì hữu ích?

+0

"Mục đích" của khả năng có thể đơn giản hóa trình phân tích cú pháp. – molbdnilo

+0

có thể trùng lặp của [Mục đích của tuyên bố như int (x) là gì; hoặc int (x) = 10;] (http://stackoverflow.com/questions/26832321/what-is-the-purpose-of-a-declaration-like-int-x-or-int-x-10) – GSerg

+1

@GSerg Vui cách văn bản câu hỏi của tôi trả lời cho câu hỏi từ câu trả lời thứ hai trong câu hỏi được liên kết của bạn, vì tôi cung cấp ví dụ cho phép khai báo như vậy dẫn đến kết quả không mong muốn :) – Predelnik

Trả lời

75

Tạo nhóm.

Là một ví dụ cụ thể, xem xét mà bạn có thể khai báo một biến kiểu chức năng như

int f(int); 

Bây giờ, làm thế nào bạn sẽ khai báo một con trỏ đến một điều như vậy?

int *f(int); 

Không, không hoạt động! Điều này được hiểu là hàm trả về int*. Bạn cần phải thêm trong ngoặc đơn để làm cho nó phân tích đúng cách:

int (*f)(int); 

Thỏa thuận tương tự với mảng:

int *x[5]; // array of five int* 
int (*x)[5]; // pointer to array of five int 
+10

Và để hoàn thành câu trả lời: không cho phép trường hợp cụ thể mà người hỏi đang hỏi về sẽ yêu cầu thêm một quy tắc đặc biệt. Định nghĩa hiện tại về cách '()' làm việc trong một kiểu là thống nhất trong suốt kiểu. –

+0

Vì vậy, trường hợp đặc biệt áp dụng cho phân tích cú pháp gây tranh cãi nhất. Điều này là do cú pháp để khởi tạo các biến với các đối số hàm tạo đã được thêm vào sau (vội vàng tôi đoán?). – AnArrayOfFunctions

+1

@FISOCPP Vâng. . Vâng. C++ đến sau C.. . – iheanyi

17

Có ấy thường được phép sử dụng dấu ngoặc đơn trong tờ khai như vậy bởi vì việc kê khai, từ điểm cú pháp của xem luôn trông như thế này:

<front type> <specification>; 

Ví dụ, trong phần khai báo sau:

012.
int* p[2]; 

"Loại trước" là int (không phải int*) và "đặc điểm kỹ thuật" là * p[2].

Quy tắc là bạn có thể sử dụng bất kỳ số lượng dấu ngoặc đơn nào khi cần trong phần "đặc điểm kỹ thuật" vì đôi khi chúng không thể tránh khỏi việc phân biệt.Ví dụ:

int* p[2]; // array of 2 pointers to int; same as int (*p[2]); 
int (*p)[2]; // pointer to an array of 2 ints 

Con trỏ đến một mảng là một trường hợp hiếm gặp, tuy nhiên tình huống tương tự mà bạn có với một con trỏ đến chức năng:

int (*func(int)); // declares a function returning int* 
int (*func)(int); // declares a pointer to function returning int 

Đây là câu trả lời trực tiếp câu hỏi của bạn. Nếu câu hỏi của bạn là về báo cáo kết quả như C(y), sau đó:

  • Đặt dấu ngoặc xung quanh toàn bộ biểu - (C(y)) và bạn sẽ nhận được những gì bạn muốn
  • Tuyên bố này không làm gì nhưng việc tạo ra một đối tượng tạm thời, mà không còn sống sau khi hướng dẫn này kết thúc (tôi hy vọng đây là những gì bạn định làm).
+1

Như tôi đã đề cập, ban đầu nó đã làm một cái gì đó trong destructor, tôi đoán đó là điều khá chuẩn khi bạn có một số số "chuỗi" các hàm để thiết lập một số tham số và sau đó thực hiện tất cả công việc trong destructor. Tuy nhiên, xin cảm ơn vì một cách giải quyết khác, tôi đoán viết '{}' là một cách hợp lệ nhất. – Predelnik

+4

cố gắng tránh tạo nên ngữ pháp của riêng bạn và sử dụng ngữ pháp được cung cấp trong tiêu chuẩn. '' gây hiểu lầm và sai. Ngữ pháp là '' –

+0

Bạn nói đúng - tôi không nhìn vào tiêu chuẩn, chỉ lặp lại quy tắc từ đầu của tôi. Trên thực tế trong C++ 11, vai trò của '' cũng có thể được chơi bởi từ khóa 'auto', vì vậy nó không phải lúc nào cũng là một kiểu. – Ethouris

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