Câu hỏi 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?


Ví dụ một tuyên bố như vậy:

int (x) = 0;

Hoặc thậm chí là:

int (((x))) = 0;

Tôi tình cờ hiểu điều này bởi vì trong đoạn code của tôi, tôi tình cờ có một đoạn giống như đoạn sau:

struct B
{
};

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

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

Rõ ràng là tôi muốn xây dựng đối tượng C mà sau đó sẽ làm một cái gì đó hữu ích trong destructor của nó. Tuy nhiên khi nó xảy ra xử lý trình biên dịch 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ư 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 của nhà xây dựng, 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 từng thấy ai thực sự sử dụng các tờ khai 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?


76
2018-04-16 13:05


gốc


"Mục đích" của khả năng có lẽ là đơn giản hóa trình phân tích cú pháp. - molbdnilo
có thể trùng lặp Mục đích của một khai báo như int (x); hoặc int (x) = 10; - GSerg
@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
stackoverflow.com/questions/6341951/… - jamesdlin


Các câu trả lời:


Nhóm.

Như một ví dụ cụ thể, hãy xem xét rằng bạn có thể khai báo một biến kiểu hàm 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 hiệu quả! Điều này được hiểu là một hàm trả về int*. Bạn cần phải thêm vào dấu ngoặc đơn để làm cho nó phân tích cú pháp đú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

76
2018-04-16 13:11



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 yêu cầu 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 thức ()làm việc trong một loại là thống nhất trong suốt loại. - Joseph Mansfield
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
@FISOCPP Vâng. . Vâng. C ++ đến sau C.. . - iheanyi
Câu trả lời này có áp dụng cho C không, không chỉ C ++? - kdbanman
"biến loại hàm" gì?!! - curiousguy


Nói chung được phép sử dụng dấu ngoặc đơn trong các khai báo như vậy vì khai báo, từ quan điểm cú pháp của kiểu nhìn luôn giống như sau:

<front type> <specification>;

Ví dụ: trong tuyên bố sau:

int* p[2];

"Loại phía trước" là int (không phải int*) và "đặc 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 hoi, tuy nhiên tình huống tương tự bạn có với một con trỏ để hoạt độ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 cho câu hỏi của bạn. Nếu câu hỏi của bạn là về tuyên bố như C(y), sau đó:

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

17
2018-04-16 13:14



Như tôi đã đề cập, ban đầu nó đã làm một cái gì đó trong destructor, tôi đoán nó khá chuẩn khi bạn có một số chức năng "chuỗi" để thiết lập một số tham số và sau đó làm tất cả công việc trong destructor. Cảm ơn vì một cách giải quyết khác, tôi đoán viết {} là cái hợp lệ nhất. - Predelnik
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. <front-type> <specification> gây hiểu lầm và sai. Ngữ pháp là <declaration-specifier> <declarator> - Steve Cox
Bạn nói đúng - tôi đã không nhìn vào tiêu chuẩn, chỉ cần lặp lại các quy tắc từ đầu của tôi. Trên thực tế trong C ++ 11 vai trò của <declaration-specifier> cũng có thể được chơi bởi auto từ khóa, vì vậy nó không phải lúc nào cũng là một loại. - Ethouris
@Pravasi Meet: Nếu bạn đã chỉnh sửa một phần bài đăng của tôi và thay đổi tên trong lược đồ cú pháp đã cho, vui lòng thay đổi tên 3 dòng bên dưới tương ứng. Nếu không, vẫn còn có tên cũ "kiểu trước" và "đặc tả" và do đó bài đăng không có ý nghĩa gì. - Ethouris