Dấu chấm phẩy sau dấu ngoặc nhọn khai báo lớp


82

Trong các lớp C ++, tại sao lại có dấu chấm phẩy sau dấu ngoặc nhọn? Tôi thường xuyên quên nó và gặp lỗi trình biên dịch, và do đó mất thời gian. Có vẻ hơi thừa đối với tôi, điều này khó có thể xảy ra. Mọi người có thực sự làm những việc như:

class MyClass
{
.
.
.
} MyInstance;

Tôi hiểu nó từ quan điểm về khả năng tương thích của C cho các cấu trúc và enum, nhưng vì các lớp không phải là một phần của ngôn ngữ C nên tôi đoán nó chủ yếu ở đó để giữ sự nhất quán giữa các cấu trúc khai báo tương tự.

Những gì tôi đang tìm kiếm liên quan nhiều đến cơ sở lý luận của thiết kế hơn là có thể thay đổi bất cứ điều gì, mặc dù một IDE hoàn thành mã tốt có thể bẫy điều này trước khi biên dịch.


4
Điều này có thể giúp đỡ: cpptalk.net/...
Michael Haren

@Michael, cảm ơn vì liên kết. Từ quan điểm lịch sử, nó có ý nghĩa tốt, và nếu C ++ cho phép tất cả C grammer, và các lớp C ++ đồng nghĩa với cấu trúc, chúng ta sẽ để lại dấu chấm phẩy cần thiết ở cuối lớp.
SmacL

3
@Brian, câu hỏi nghiêm túc đấy. Tôi biết rõ mình phải sống với nó nhưng tôi tò mò về cơ sở lý luận đằng sau việc thiết kế và thực hiện.
SmacL

Được rồi, nhưng có lẽ bạn nên chỉnh sửa câu hỏi của mình để bao gồm cơ sở thiết kế bạn muốn. Nó khuyến khích mọi người đặt những câu hỏi như "tại sao lại có dấu ngoặc nhọn"? :) Bạn có thể quan tâm đến việc đọc Stroustrup's Design & Evolution of C ++, mặc dù nó bao gồm nhiều vấn đề nặng nề hơn so với dấu chấm phẩy ở cuối các lớp.
Brian Neal

@Brian, đủ công bằng, và nó là ranh giới về việc có nên wiki nó hay không. Câu hỏi được đặt ra sau khi bỏ dấu chấm phẩy trong tiêu đề được sử dụng thường xuyên trong một bản dựng lớn. Tôi mất nửa giờ, do đó chuyến thăm đến SO. Câu hỏi được chỉnh sửa theo đề xuất của bạn.
SmacL

Câu trả lời:


47

Dấu chấm phẩy sau dấu ngoặc nhọn đóng trong khai báo kiểu được ngôn ngữ yêu cầu. Nó đã theo cách đó kể từ những phiên bản đầu tiên của C.

Và vâng, mọi người thực sự làm theo tuyên bố mà bạn vừa đưa ra ở đó. Nó hữu ích cho việc tạo các loại phạm vi bên trong các phương thức.

void Example() {
  struct { int x; } s1;
  s1.x = 42;

  struct ADifferentType { int x; };
}

Trong trường hợp này, tôi nghĩ rõ ràng tại sao lại cần dấu chấm phẩy. Về lý do tại sao nó lại cần trong trường hợp tổng quát hơn là khai báo trong tệp tiêu đề, tôi không chắc. Tôi đoán rằng đó là lịch sử và đã được thực hiện để giúp việc viết trình biên dịch dễ dàng hơn.


Tại sao tôi không thể chỉ tạo loại phạm vi mà không chỉ định MyInstance? Nó kết hợp kỳ lạ khi bạn kết hợp hai hành động: khai báo kiểu mới và khai báo biến mới.
Mykola Golubyev

@Mykola bạn có thể làm cả hai. Xem mẫu tôi đã thêm
JaredPar

70

Các liên kết được cung cấp bởi @MichaelHaren xuất hiện để cung cấp các nguyên nhân gốc rễ . Dấu chấm phẩy (như những người khác đã chỉ ra) được kế thừa từ C. Nhưng điều đó không giải thích tại sao C sử dụng nó ngay từ đầu. Cuộc thảo luận này bao gồm một ví dụ:

struct fred { int x; long y; }; 
main() 
{ 
  return 0; 
} 

Các phiên bản cũ hơn của C có kiểu trả về int ngầm định từ một hàm trừ khi được khai báo khác. Nếu chúng ta bỏ qua phần ;cuối của định nghĩa cấu trúc, chúng ta không chỉ định nghĩa một kiểu mới fredmà còn khai báo rằng main()sẽ trả về một thể hiện của fred. Tức là mã sẽ được phân tích cú pháp như thế này:

struct fred { int x; long y; } main()
{ 
  return 0; /* invalid return type, expected fred type */
} 

1
Yeah, kiểu trả về int ngầm định sẽ có hiệu lực mọi thứ ở đây. Nice gem
Gaspa79,

17

Tôi đoán đó là bởi vì các lớp là khai báo, ngay cả khi chúng cần dấu ngoặc nhọn để nhóm. Và có, có một lập luận lịch sử rằng kể từ trong C, bạn có thể làm

struct
{
  float x;
  float y;
} point;

bạn sẽ có thể làm điều tương tự trong C ++, điều đó có ý nghĩa khi classkhai báo hoạt động theo cùng một cách.


10

Nó viết tắt của

class MyClass
{
.
.
.
};

// instance declaration
MyClass MyInstance;  // semicolon here

Dấu chấm phẩy sau dấu ngoặc nhọn của khai báo lớp thực sự là quá mức cần thiết, nhưng đó là cách C ++ được định nghĩa. Dấu chấm phẩy sau phần khai báo biến luôn cần thiết và có ý nghĩa.


1
Vì vậy, C ++ có yêu cầu dấu chấm phẩy sau mỗi khai báo không?
Loai Nagati

1
Lưu ý rằng, theo cách này, bạn không thể tạo một đối tượng của một lớp ẩn danh, trong khi bạn có thể làm theo cách khác.
Kevin

5

Tôi không sử dụng các khai báo như vậy

class MyClass
{
.
.
.
} MyInstance;

Nhưng trong trường hợp này tôi có thể hiểu tại sao lại có dấu chấm phẩy ở đó.
Vì nó giống như int a;- khai báo biến.

Có thể là để nhất quán vì bạn có thể bỏ qua dấu chấm phẩy 'MyInstance' vẫn ở đó.


3

Nó là cần thiết sau một structvì lý do tương thích và bạn muốn điều này như thế nào:

struct MyStruct { ... };
class  MyClass  { ... }    //inconsistency

1
Nhưng những gì về namespace myNamespace { ... } // inconsistent but valid?
Chris K,

3

Trong C / C ++ các; là một kết thúc câu lệnh. Tất cả các câu lệnh được kết thúc bằng; để tránh sự mơ hồ (và để đơn giản hóa việc phân tích cú pháp). Ngữ pháp nhất quán về mặt này. Mặc dù một khai báo lớp (hoặc bất kỳ khối nào cho vấn đề đó) dài nhiều dòng và được phân tách bằng {} thì nó vẫn chỉ đơn giản là một câu lệnh ({} là một phần của câu lệnh) do đó cần được kết thúc bằng; (Dấu; không phải là dấu phân tách / dấu phân cách)

Trong ví dụ của bạn

class MyClass{...} MyInstance;

là câu hoàn chỉnh. Người ta có thể xác định nhiều trường hợp của lớp đã khai báo trong một câu lệnh duy nhất

class MyClass{...} MyInstance1, MyInstance2;

Điều này hoàn toàn phù hợp với việc khai báo nhiều trường hợp của kiểu nguyên thủy trong một câu lệnh:

int a, b, c;

Lý do mà người ta không thường xuyên thấy các mô tả như vậy về lớp và cá thể, là trường hợp có thể? là một biến toàn cục và bạn không thực sự muốn các đối tượng toàn cục trừ khi chúng là cấu trúc tĩnh và / hoặc cấu trúc Dữ liệu cũ thuần túy.


2
Nhưng định nghĩa hàm cũng là một câu lệnh nhưng không có dấu chấm phẩy.
Jiapeng Zhang
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.