Khi nào bạn nên sử dụng một lớp so với một cấu trúc trong C ++?


950

Trong trường hợp nào là tốt hơn để sử dụng structso với a classtrong C ++?


48
Điều này không chỉ áp dụng cho C ++, mà với bất kỳ ngôn ngữ nào cung cấp cả cấu trúc và lớp.
Jason Bunting

3
Tôi vẫn không đồng ý - Tôi tiếp cận câu hỏi này về mặt ngữ nghĩa. Có thể có một số khác biệt về kỹ thuật, nhưng về mặt ngữ nghĩa, chúng không có. Structs thực sự hữu ích để tạo các loại giá trị, các lớp thì không.
Jason Bunting

4
Tôi tin rằng không có lý do nghiêm trọng nào cho việc sử dụng cấu trúc trong C ++. Đối với tôi, cấu trúc là một "tính năng" dự phòng khác của C ++ chỉ tồn tại để tương thích với C, như typedefs. Chúng sẽ không tồn tại nếu C ++ ban đầu không được coi là phần mở rộng của C và được thiết kế từ đầu, chẳng hạn như Java. Nói chung, tôi thấy rằng nhiều điều kỳ lạ nhất về C ++ phải làm với khả năng tương thích C.
Kostas

5
Struct - Đối với POD (dữ liệu cũ đơn giản) và tất cả khả năng truy cập của thành viên là công khai. Lớp - Khi bạn cần đóng gói tốt hơn và cần các hàm thành viên để làm việc với trạng thái của lớp.
Navaneeth KN

4
Điều này chỉ đúng theo quy ước. Không có sự khác biệt, ngoài đóng gói mặc định.
Dave Hillier

Câu trả lời:


805

Sự khác biệt giữa a classvà a structtrong C ++ là các cấu trúc có publiccác thành viên mặc định và các cơ sở và các lớp có privatecác thành viên và cơ sở mặc định . Cả lớp và cấu trúc có thể có một hỗn hợp của public, protectedprivatecác thành viên, có thể sử dụng thừa kế và có thể có hàm thành viên.

Tôi sẽ khuyên bạn nên sử dụng các cấu trúc như các cấu trúc dữ liệu cũ đơn giản mà không có bất kỳ tính năng nào giống như lớp và sử dụng các lớp làm cấu trúc dữ liệu tổng hợp với privatecác hàm thành viên và dữ liệu.


100
Một cấu trúc không có sửa đổi hoặc phương thức được gọi là cấu trúc POD, tồn tại dưới dạng giao diện tương thích ngược với các thư viện C vì nó (được cho là) ​​được đảm bảo được đặt ra như thể nó là cấu trúc C. Ngoài một ngoại lệ này, sự khác biệt duy nhất là như đã nêu.
workmad3

26
@ workmad3: Tên này gây hiểu nhầm, nhưng 9/4 (C ++ 03) nói: "POD-struct là một lớp tổng hợp không có thành viên dữ liệu không tĩnh thuộc loại không POD-struct, không POD-union (hoặc mảng các loại như vậy) hoặc tham chiếu và không có toán tử gán sao chép do người dùng định nghĩa và không có hàm hủy do người dùng xác định. " Không có hạn chế trong việc sử dụng khóa lớp "struct" và không hạn chế sử dụng "công khai" (xem 8.5.1 / 1 cho các yêu cầu tổng hợp). Đây không phải là một sự khác biệt giữa "struct" và "class".

5
Việc sử dụng "tổng hợp" của bạn có thể bị hiểu nhầm, dựa trên định nghĩa của tiêu chuẩn. :)

3
Theo cuốn sách "Nguyên tắc và thực hành" của Stroustrup: "chủ yếu nên sử dụng các cấu trúc trong đó các thành viên có thể nhận bất kỳ giá trị nào" (nghĩa là không thể xác định được bất biến lớp có ý nghĩa)
kháng sinh

6
Tất nhiên bạn có thể sử dụng các lớp khi giao tiếp với C. Không có sự khác biệt giữa các lớp và cấu trúc. Cấu trúc là các lớp học; chỉ truy cập mặc định được lật từ riêng tư sang công cộng.
Sebastian Mach

230

Như mọi người khác lưu ý, thực sự chỉ có hai sự khác biệt về ngôn ngữ:

  • structmặc định truy cập công cộng và classmặc định truy cập riêng.
  • Khi thừa kế, structmặc định là publicthừa kế và classmặc định là privatethừa kế. (Trớ trêu thay, cũng như rất nhiều thứ trong C ++, mặc định là ngược: publickế thừa là lựa chọn phổ biến hơn, nhưng mọi người hiếm khi tuyên bố structs chỉ để tiết kiệm khi gõ publictừ khóa "".

Nhưng sự khác biệt thực tế trong thực tế là giữa a class/ structkhai báo hàm tạo / hàm hủy và một hàm không. Có một số đảm bảo nhất định đối với loại POD "dữ liệu cũ", không còn áp dụng khi bạn tiếp quản công trình của lớp. Để giữ sự khác biệt này rõ ràng, nhiều người cố tình chỉ sử dụng structs cho các loại POD và nếu họ sẽ thêm bất kỳ phương thức nào, hãy sử dụng classes. Sự khác biệt giữa hai mảnh dưới đây là vô nghĩa:

class X
{
  public:

  // ...
};

struct X
{
  // ...
};

(Ngẫu nhiên, đây là một chủ đề với một số giải thích tốt về "loại POD" thực sự có nghĩa là : Các loại POD trong C ++ là gì? )


Ví dụ đẹp về sự khác biệt thừa kế: ở đây .
Liran Orevi

8
Cho dù bạn sử dụng structhay classkhông có liên quan đến việc đối tượng của bạn là POD hay bạn nên xác định hàm tạo / hàm hủy sao chép. Các chức năng thành viên cũng không có liên quan đến một cái gì đó là POD. Khi tôi đọc lại những gì bạn đã viết, tôi thấy bạn không gợi ý gì khác, nhưng cách diễn đạt hiện tại thật khó hiểu
David Stone

1
@DavidStone Về cơ bản, các cấu trúc POD được cho là được đảm bảo tương thích ngược với mã C, và do đó về cơ bản được cho là chỉ được thiết kế theo cấu trúc kiểu C.
Thời gian của Justin - Tái lập Monica

3
Phần "khác biệt thực sự" của câu trả lời này là hoàn toàn sai.
juanchopanza

178

Có rất nhiều quan niệm sai lầm trong các câu trả lời hiện có.

Cả hai classstructtuyên bố một lớp.

Có, bạn có thể phải sắp xếp lại các từ khóa sửa đổi truy cập của mình bên trong định nghĩa lớp, tùy thuộc vào từ khóa bạn đã sử dụng để khai báo lớp.

Nhưng, ngoài cú pháp, lý do duy nhất để chọn cái này là cái khác là quy ước / kiểu / sở thích.

Một số người thích gắn bó với structtừ khóa cho các lớp không có hàm thành viên, vì định nghĩa kết quả "trông giống như" một cấu trúc đơn giản từ C.

Tương tự, một số người thích sử dụng classtừ khóa cho các lớp có chức năng và privatedữ liệu thành viên , vì nó nói "lớp" trên đó và do đó trông giống như các ví dụ từ cuốn sách yêu thích của họ về lập trình hướng đối tượng.

Thực tế là điều này hoàn toàn phụ thuộc vào bạn và nhóm của bạn, và nó sẽ thực sự không có gì khác biệt đối với chương trình của bạn.

Hai lớp sau đây hoàn toàn tương đương theo mọi cách trừ tên của chúng:

struct Foo
{
   int x;
};

class Bar
{
public:
   int x;
};

Bạn thậm chí có thể chuyển từ khóa khi khai báo lại:

class Foo;
struct Bar;

(mặc dù điều này phá vỡ các bản dựng Visual Studio do không tuân thủ, do đó trình biên dịch sẽ phát ra cảnh báo khi bạn thực hiện việc này.)

và các biểu thức sau đây đều đánh giá là đúng:

std::is_class<Foo>::value
std::is_class<Bar>::value

Tuy nhiên, xin lưu ý rằng bạn không thể chuyển từ khóa khi xác định lại ; điều này chỉ bởi vì (theo quy tắc một định nghĩa) các định nghĩa lớp trùng lặp giữa các đơn vị dịch phải "bao gồm cùng một chuỗi các mã thông báo" . Điều này có nghĩa bạn thậm chí không thể trao đổi const int member;với int const member;, và không có gì để làm với các ngữ nghĩa của classhay struct.


16
Điều này rất nhiều thông tin, và thành thật câu trả lời yêu thích của tôi. Mọi người khác đang coi họ như những thực thể riêng biệt, khi bên dưới mui xe, họ giống nhau. Tôi tự hỏi nếu một định nghĩa cấu trúc trong môi trường Arduino được coi là một lớp cpp, xem như nó được biên dịch bằng g ++.
Benjamin

4
@Ben Tất nhiên rồi. Trình biên dịch Arduino biên dịch C ++; đó là kết thúc của nó
gạch dưới

7
Vì vậy, nếu tôi hiểu đúng về điều này: Miễn là các công cụ sửa đổi khả năng hiển thị của bạn rõ ràng, không bị bỏ qua, điều đó không thành vấn đề. Bạn có thể viết một ứng dụng C ++ khổng lồ bằng cách sử dụng không có gì ngoài các cấu trúc; hoặc bạn có thể đi qua và thay đổi mọi trường hợp của struct sang lớp. Miễn là bạn không sử dụng khả năng hiển thị mặc định, các ứng dụng sẽ hoàn toàn giống nhau.
Ryan Lundy

Tôi không tin rằng một đơn vị dịch thuật của chương trình C ++ có thể có tuyên bố hoàn chỉnh class foo { public: ... };và một đơn vị dịch thuật khác có thể phải struct foo { ... };giữ đúng theo yêu cầu "hoàn toàn tương đương". Lý do là các tuyên bố không đầy đủ struct foo;class foo;có thể thay thế cho nhau. Chúng không chỉ định nội dung lớp và vì vậy chúng không nói gì đến bố cục truy cập.
Kaz

@Kaz: Bạn đã đúng - nếu các định nghĩa là cùng loại theo nghĩa đen, thì chúng phải giống hệt nhau về mặt từ vựng để hành vi được xác định rõ. Các struct-keyđẳng cấp chính là khác một cách hợp lý mặc dù trao đổi (trong đó ngữ nghĩa không bị ảnh hưởng), và FooBarvẫn còn tương đương / loại giống hệt nhau. Tôi đã chắc chắn nói "khi khai báo lại " và đưa ra một ví dụ. Nghĩ về nó, tôi sẽ làm rõ điều này trong câu trả lời để đảm bảo rằng tôi không lừa dối mọi người vào UB
Các cuộc đua nhẹ nhàng trong quỹ đạo

54

Lần duy nhất tôi sử dụng struct thay vì một lớp là khi khai báo functor ngay trước khi sử dụng nó trong một lệnh gọi hàm và muốn giảm thiểu cú pháp vì mục đích rõ ràng. ví dụ:

struct Compare { bool operator() { ... } };
std::sort(collection.begin(), collection.end(), Compare()); 

35
Bây giờ là vài năm sau và C ++ 11 được hỗ trợ bởi tất cả các trình biên dịch chính, Lambdas làm cho điều này thậm chí ngắn gọn hơn .

36

Từ C ++ FAQ Lite :

Các thành viên và các lớp cơ sở của một cấu trúc được công khai theo mặc định, trong khi trong lớp, chúng mặc định là riêng tư. Lưu ý: bạn nên làm cho các lớp cơ sở của mình rõ ràng công khai, riêng tư hoặc được bảo vệ, thay vì dựa vào các mặc định.

struct và class khác có chức năng tương đương.

OK, đủ nói chuyện kỹ thuật sạch sẽ khó chịu. Về mặt tình cảm, hầu hết các nhà phát triển tạo ra sự khác biệt mạnh mẽ giữa một lớp và một cấu trúc. Một cấu trúc chỉ đơn giản cảm thấy giống như một đống bit mở với rất ít cách thức đóng gói hoặc chức năng. Một lớp học cảm thấy như một thành viên sống và có trách nhiệm với xã hội với các dịch vụ thông minh, rào cản đóng gói mạnh mẽ và giao diện được xác định rõ. Vì đó là ý nghĩa mà hầu hết mọi người đã có, nên có lẽ bạn nên sử dụng từ khóa struct nếu bạn có một lớp có rất ít phương thức và có dữ liệu công khai (những thứ đó tồn tại trong các hệ thống được thiết kế tốt!), Nhưng nếu không thì có lẽ bạn nên sử dụng lớp từ khóa.


1
Tôi không hiểu tại sao họ lại nói rằng struct và class có chức năng giống nhau, nhưng nói rằng thích cái này hơn cái kia trong một số trường hợp nhất định mà không có lý do nào ..
deetz

3
Lý do là quy ước. Trình biên dịch không quan tâm bạn sử dụng cái nào, nhưng một nhà phát triển khác đang xem mã của bạn sẽ dễ hiểu hơn về ý nghĩa của bạn.
Tal Pressman

3
@deetz: Toàn bộ đoạn thứ ba là lý luận.
Các cuộc đua nhẹ nhàng trong quỹ đạo

Wow, đến từ 'trường học cũ' Tôi không biết rằng một cấu trúc có thể có phương thức và thậm chí cả sự kế thừa. Tôi đã luôn sử dụng struct khi chỉ sử dụng dữ liệu mà không có phương thức và thường là khi xử lý mã API cần cấu trúc. Cấu trúc có thể hỗ trợ nhiều kế thừa cũng không?
Paul McCarthy

21

Một nơi mà một cấu trúc có ích cho tôi là khi tôi có một hệ thống nhận các tin nhắn định dạng cố định (nói chung là một cổng nối tiếp) từ một hệ thống khác. Bạn có thể truyền luồng byte thành một cấu trúc xác định các trường của bạn và sau đó dễ dàng truy cập vào các trường.

typedef struct
{
    int messageId;
    int messageCounter;
    int messageData;
} tMessageType;

void processMessage(unsigned char *rawMessage)
{
    tMessageType *messageFields = (tMessageType *)rawMessage;
    printf("MessageId is %d\n", messageFields->messageId);
}

Rõ ràng, đây là điều tương tự bạn sẽ làm trong C, nhưng tôi thấy rằng chi phí chung của việc phải giải mã tin nhắn thành một lớp thường không đáng.


Điều tương tự cũng có thể đạt được ở C.
Eugene Bujak

11
Hoặc bạn chỉ có thể thực hiện operator >>trên một lớp thay vì viết processMessagehàm, điều này sẽ làm cho C ++ của bạn trông giống C ++ hơn và giống như C.
Nick Bastin

1
Bên cạnh thực tế là nó không di động giữa các hệ thống khác nhau, điều này vi phạm các quy tắc răng cưa, do đó, nó không được đảm bảo để hoạt động ngay cả trong một kiến ​​trúc duy nhất.
gạch dưới

@underscore_d Điều này có thể hoạt động độc lập với nền tảng (nhưng không phải trình biên dịch), nhưng bạn phải sử dụng các bitfield cố định, một __packed__cấu trúc và có một triển khai ifdef nhận biết endian (bạn cần lật thứ tự trên một máy trong đó endianess đối diện với nguồn dữ liệu ngoài Đang cung cấp). Nó không đẹp, nhưng tôi đã sử dụng để đóng gói / giải nén các thanh ghi cho các thiết bị ngoại vi từ xa trên các nền tảng nhúng theo cách di động.
crasic

1
@jacwah Huh, điểm tốt. Bí danh sẽ không là vấn đề ở đây vì một trong những con trỏ là một charloại, được miễn trừ răng cưa. Tuy nhiên, vẫn còn một vấn đề, mặc dù có một vấn đề khác: Đúc một char*loại khác, nếu thực sự không có bất kỳ đối tượng nào thuộc loại sau đã được khởi tạo tại địa chỉ đó, thì đó là UB vì nó vi phạm quy tắc trọn đời. Afaik, ngay cả khi loại đích có thể xây dựng tầm thường, chỉ cần có bộ nhớ được cấp phát là không đủ cho C ++ để chính thức cho phép coi bộ nhớ đó là loại đó.
gạch dưới

19

Bạn có thể sử dụng "struct" trong C ++ nếu bạn đang viết thư viện có phần bên trong là C ++ nhưng API có thể được gọi bằng mã C hoặc C ++. Bạn chỉ cần tạo một tiêu đề duy nhất chứa các cấu trúc và các hàm API toàn cầu mà bạn hiển thị cho cả mã C và C ++ như sau:

// C access Header to a C++ library
#ifdef __cpp
extern "C" {
#endif

// Put your C struct's here
struct foo
{
    ...
};
// NOTE: the typedef is used because C does not automatically generate
// a typedef with the same name as a struct like C++.
typedef struct foo foo;

// Put your C API functions here
void bar(foo *fun);

#ifdef __cpp
}
#endif

Sau đó, bạn có thể viết một thanh chức năng () trong tệp C ++ bằng mã C ++ và làm cho nó có thể gọi được từ C và hai thế giới có thể chia sẻ dữ liệu thông qua các cấu trúc được khai báo. Tất nhiên có những cảnh báo khác khi trộn C và C ++ nhưng đây là một ví dụ đơn giản.


2
Câu trả lời phù hợp nhất. Khả năng tương thích C thực sự là lý do quan trọng nhất. tất cả những thứ khác như truy cập mặc định là bí truyền.
Valentin Heinitz

16

Như mọi người nói, sự khác biệt thực sự duy nhất là truy cập mặc định. Nhưng tôi đặc biệt sử dụng struct khi tôi không muốn bất kỳ kiểu đóng gói nào với một lớp dữ liệu đơn giản, ngay cả khi tôi thực hiện một số phương thức trợ giúp. Ví dụ, khi tôi cần một cái gì đó như thế này:

struct myvec {
    int x;
    int y;
    int z;

    int length() {return x+y+z;}
};

1
+1 để đưa ra ví dụ về cấu trúc với một số chức năng thành viên mà không cảm thấy như bạn đã "lấy đi cấu trúc".
einpoklum

9

Để trả lời câu hỏi của riêng tôi (không biết xấu hổ), Như đã đề cập, đặc quyền truy cập là sự khác biệt duy nhất giữa chúng trong C ++.

Tôi có xu hướng chỉ sử dụng một cấu trúc để lưu trữ dữ liệu. Tôi sẽ cho phép nó có được một vài chức năng trợ giúp nếu nó làm việc với dữ liệu dễ dàng hơn. Tuy nhiên, ngay khi dữ liệu yêu cầu kiểm soát luồng (tức là getters / setters duy trì hoặc bảo vệ trạng thái bên trong) hoặc bắt đầu thực hiện bất kỳ chức năng chính nào (về cơ bản giống như đối tượng hơn), nó sẽ được 'nâng cấp' lên một lớp để có ý định giao tiếp tốt hơn.


9

Cấu trúc ( POD , nói chung hơn) rất tiện lợi khi bạn cung cấp giao diện tương thích C với triển khai C ++, vì chúng có thể di chuyển qua biên giới ngôn ngữ và các định dạng liên kết.

Nếu điều đó không liên quan đến bạn, thì tôi cho rằng việc sử dụng "struct" thay vì "class" là một người truyền đạt ý định tốt (như @ZeroSignal đã nói ở trên). Structs cũng có ngữ nghĩa sao chép dễ dự đoán hơn, vì vậy chúng hữu ích cho dữ liệu bạn định ghi vào phương tiện bên ngoài hoặc gửi qua dây.

Các cấu trúc cũng tiện dụng cho các tác vụ siêu lập trình khác nhau, như các mẫu đặc điểm chỉ phơi bày một loạt các typedefs phụ thuộc:

template <typename T> struct type_traits {
  typedef T type;
  typedef T::iterator_type iterator_type;
  ...
};

... Nhưng đó thực sự chỉ là lợi dụng mức độ bảo vệ mặc định của struct là công khai ...


1
Đó không phải là cách sử dụng đúng của POD. Một struct (hoặc lớp) có thể là POD struct nếu (và chỉ khi) nó chỉ chứa các thành viên POD.
Martin York

4
"ngữ nghĩa sao chép dự đoán": Các biểu tượng tương tự như đối với lớp (và có cùng các vấn đề (bản sao nông)).
Martin York

2
Bài đăng này sẽ khiến bạn tin rằng (hy vọng là tình cờ) rằng tất cả các cấu trúc là POD. Điều này hoàn toàn không đúng. Tôi hy vọng rằng mọi người không bị lừa dối bởi điều này.
Michael Dorst

8

Đối với C ++, thực sự không có nhiều sự khác biệt giữa các cấu trúc và các lớp. Sự khác biệt về chức năng chính là các thành viên của một cấu trúc được công khai theo mặc định, trong khi chúng là riêng tư theo mặc định trong các lớp. Mặt khác, theo như ngôn ngữ có liên quan, chúng là tương đương.

Điều đó nói rằng, tôi có xu hướng sử dụng các cấu trúc trong C ++ giống như tôi làm trong C #, tương tự như những gì Brian đã nói. Structs là các thùng chứa dữ liệu đơn giản, trong khi các lớp được sử dụng cho các đối tượng cần hành động trên dữ liệu ngoài việc chỉ giữ nó.


4

Họ là khá nhiều điều tương tự. Nhờ vào phép thuật của C ++, một cấu trúc có thể giữ các hàm, sử dụng tính kế thừa, được tạo bằng cách sử dụng "mới" và cứ như vậy giống như một lớp

Sự khác biệt duy nhất về chức năng là một lớp bắt đầu bằng quyền truy cập riêng, trong khi cấu trúc bắt đầu bằng công khai. Đây là khả năng tương thích ngược với C.

Trong thực tế, tôi luôn sử dụng các cấu trúc như các chủ sở hữu dữ liệu và các lớp làm đối tượng.


4

Như những người khác đã chỉ ra

  • cả hai đều tương đương ngoài khả năng hiển thị mặc định
  • có thể có lý do để buộc phải sử dụng cái này hay cái kia vì bất kỳ lý do gì

Có một khuyến nghị rõ ràng về thời điểm sử dụng từ Stroustrup / Sutter:

Sử dụng lớp nếu lớp có bất biến; sử dụng struct nếu các thành viên dữ liệu có thể thay đổi độc lập

Tuy nhiên, hãy nhớ rằng không phải là khôn ngoan để chuyển tiếp tuyên bố sth. như một lớp ( class X;) và định nghĩa nó là struct ( struct X { ... }). Nó có thể hoạt động trên một số trình liên kết (ví dụ: g ++) và có thể thất bại với những người khác (ví dụ: MSVC), vì vậy bạn sẽ thấy mình trong địa ngục của nhà phát triển.


Bạn có thể mô tả các vấn đề liên kết?
Các cuộc đua nhẹ nhàng trong quỹ đạo

@LightnessRacesinOrbit Tôi không thể, thật không may. Tôi thậm chí không thể tạo ra một ví dụ. Tầm thường class Foo; struct Foo { void bar() {} }; int main() { Foo().bar(); }không chỉ biên dịch và chạy với MSVC 2017, nó thậm chí còn tạo ra một cảnh báo rõ ràng Foođược tuyên bố là structnhưng được định nghĩa là class. Nhưng tôi cũng nhớ rõ rằng phải mất nửa ngày để tìm ra con bọ ngu ngốc đó. Tôi không chắc chắn phiên bản MSVC nào chúng tôi đã sử dụng trước đó.
pasbi

Trình liên kết thậm chí không biết về việc bạn đã sử dụng classhay structkhai báo chuyển tiếp và cả hai có thể thay thế tự do theo tiêu chuẩn (mặc dù người ta biết rằng VS cảnh báo; tôi luôn cho rằng đó chỉ là để tránh những lỗi lập trình rõ ràng). Một cái gì đó không có mùi ngay tại đây. Bạn có chắc chắn đó không phải là lỗi vi phạm ODR?
Các cuộc đua nhẹ nhàng trong quỹ đạo


Tôi không nhớ chính xác. Vấn đề không xảy ra trực tiếp trong một ứng dụng, nhưng trong một thư viện được sử dụng trong gtest. Tôi chỉ biết rằng trình liên kết tạo ra các lỗi không thể hiểu được (LNK ???). Khi tôi thay thế từ structtrước đến sau class, các vấn đề sẽ biến mất. Đến hôm nay, tôi cũng thấy lạ. Tôi rất vui nếu bạn có thể làm sáng tỏ nó.
pasbi

3

Lớp học.

Các thành viên lớp là mặc định.

class test_one {
    int main_one();
};

Tương đương với

class test_one {
  private:
    int main_one();
};

Vì vậy, nếu bạn cố gắng

int two = one.main_one();

Chúng tôi sẽ nhận được một lỗi: main_one is privatebởi vì nó không thể truy cập. Chúng ta có thể giải quyết nó bằng cách khởi tạo nó bằng cách chỉ định công khai tức là

class test_one {
  public:
    int main_one();
};

Cấu trúc.

Một struct là một lớp nơi các thành viên được công khai theo mặc định.

struct test_one {
    int main_one;
};

Có nghĩa main_onelà riêng tư tức là

class test_one {
  public:
    int main_one;
};

Tôi sử dụng các cấu trúc cho các cấu trúc dữ liệu trong đó các thành viên có thể nhận bất kỳ giá trị nào, cách đó dễ dàng hơn.


3

Một lợi thế của structtrên classlà nó tiết kiệm một dòng mã, nếu tôn trọng "các thành viên công khai đầu tiên, sau đó tin". Trong ánh sáng này, tôi thấy từ khóa classvô dụng.

Đây là một lý do khác để chỉ sử dụng structvà không bao giờ class. Một số nguyên tắc kiểu mã cho C ++ đề xuất sử dụng các chữ cái nhỏ cho macro chức năng, lý do là khi macro được chuyển đổi thành hàm nội tuyến, không nên thay đổi tên. Tương tự ở đây. Bạn có cấu trúc kiểu C đẹp và một ngày nào đó, bạn phát hiện ra rằng bạn cần thêm một hàm tạo, hoặc một số phương thức tiện lợi. Bạn có thay đổi nó thành một class? Mọi nơi?

Phân biệt giữa structs và classes chỉ là quá nhiều rắc rối, đi vào cách làm những gì chúng ta nên làm - lập trình. Giống như rất nhiều vấn đề của C ++, nó nảy sinh từ mong muốn mạnh mẽ về khả năng tương thích ngược.


Tại sao bạn cần phải thay đổi nó thành một class? Bạn có nghĩ rằng một lớp được xác định bằng structtừ khóa không thể có các hàm thành viên hoặc hàm tạo không?
Các cuộc đua nhẹ nhàng trong quỹ đạo

@LightnessRacesinOrbit vì 1. tính nhất quán và 2. một số máy phân tích tĩnh phàn nàn về vi phạm của 1.
Vorac

Điều đó không tuân theo. Những "tính nhất quán" nào khác mà bạn tuân thủ? Mỗi lớp với một thành viên được gọi joe()phải được xác định với classtừ khóa? Mỗi lớp có ít nhất 4 intthành viên phải được xác định bằng structtừ khóa?
Các cuộc đua nhẹ nhàng trong quỹ đạo

@LightnessRacesinOrbit Tôi đang đề cập đến thành ngữ "tập hợp POD được định nghĩa với struct, tập hợp với các phương thức được định nghĩa bằng class". Quá nhiều rắc rối.
Vorac

2

chúng giống nhau với các mặc định khác nhau (mặc định là riêng tư và mặc định là classcông khai struct), vì vậy về mặt lý thuyết chúng hoàn toàn có thể hoán đổi cho nhau.

vì vậy, nếu tôi chỉ muốn gói một số thông tin để di chuyển, tôi sử dụng một cấu trúc, ngay cả khi tôi đặt một vài phương thức ở đó (nhưng không nhiều). Nếu đó là một thứ không rõ ràng, trong đó việc sử dụng chính sẽ thông qua các phương thức và không trực tiếp đến các thành viên dữ liệu, tôi sử dụng một lớp đầy đủ.


2

Các cấu trúc theo mặc định có quyền truy cập công khai và các lớp theo mặc định có quyền truy cập riêng.

Cá nhân tôi sử dụng các cấu trúc cho các đối tượng truyền dữ liệu hoặc làm đối tượng giá trị. Khi được sử dụng như vậy tôi khai báo tất cả các thành viên là const để ngăn sửa đổi bởi mã khác.


2

Cả hai structclassđều giống nhau dưới mui xe mặc dù với các mặc định khác nhau về khả năng hiển thị, structmặc định là công khai và classmặc định là riêng tư. Bạn có thể thay đổi cái này thành cái khác với cách sử dụng privatepublic. Cả hai đều cho phép kế thừa, phương thức, hàm tạo, hàm hủy và tất cả các tính năng còn lại của ngôn ngữ hướng đối tượng.

Tuy nhiên, một điểm khác biệt lớn giữa hai loại đó structlà từ khóa được hỗ trợ trong C trong khi đó classthì không. Điều này có nghĩa là người ta có thể sử dụng một structtệp bao gồm có thể #includevào C ++ hoặc C miễn structlà kiểu C đơn giản structvà mọi thứ khác trong tệp đính kèm đều tương thích với C, tức là không có từ khóa cụ thể C ++ nào private, như public, không phương pháp, không kế thừa, v.v.

Kiểu AC structcó thể được sử dụng với các giao diện khác hỗ trợ sử dụng kiểu C structđể truyền dữ liệu qua lại trên giao diện.

Phong cách AC structlà một loại mẫu (không phải mẫu C ++ mà là mẫu hoặc khuôn tô) mô tả bố cục của vùng nhớ. Trong những năm qua các giao diện sử dụng được từ C và C với plug-ins (ở đây đang nhìn vào bạn Java và Python và Visual Basic) đã được tạo ra một số trong đó làm việc với C phong cách struct.


1

Về mặt kỹ thuật cả hai đều giống nhau trong C ++ - ví dụ, một cấu trúc có thể có các toán tử quá tải, v.v.

Tuy nhiên :

Tôi sử dụng các cấu trúc khi tôi muốn truyền thông tin của nhiều loại đồng thời Tôi sử dụng các lớp khi tôi đang xử lý một đối tượng "chức năng".

Hy vọng nó giúp.

#include <string>
#include <map>
using namespace std;

struct student
{
    int age;
    string name;
    map<string, int> grades
};

class ClassRoom
{
    typedef map<string, student> student_map;
  public :
    student getStudentByName(string name) const 
    { student_map::const_iterator m_it = students.find(name); return m_it->second; }
  private :
    student_map students;
};

Chẳng hạn, tôi đang trả lại một sinh viên theo cấu trúc trong các phương thức get ... () ở đây - thưởng thức.


1

Khi nào bạn sẽ chọn sử dụng struct và khi nào sử dụng lớp trong C ++?

Tôi sử dụng structkhi tôi xác định functorsPOD. Nếu không thì tôi dùng class.

// '()' is public by default!
struct mycompare : public std::binary_function<int, int, bool>
{
    bool operator()(int first, int second)
    { return first < second; }
};

class mycompare : public std::binary_function<int, int, bool>
{
public:
    bool operator()(int first, int second)
    { return first < second; }
};

1
Câu trả lời này đang có dấu hiệu tuổi tác :) std::binary_function<>không chỉ bị phản đối, c ++ 17 thậm chí còn loại bỏ nó.
sehe

Không có gì đáng ngạc nhiên vì nó được viết vào thời của C ++ 03, một ngôn ngữ được định nghĩa 15 năm trước.
Các cuộc đua nhẹ nhàng trong quỹ đạo

1

Tôi sử dụng structs khi tôi cần tạo loại POD hoặc functor.


1

Tất cả các thành viên lớp là riêng tư theo mặc định và tất cả các thành viên cấu trúc được công khai theo mặc định. Lớp có các cơ sở riêng mặc định và Struct có các cơ sở công cộng mặc định. Struct trong trường hợp C không thể có các hàm thành viên trong trường hợp của C ++, chúng ta có thể có các hàm thành viên được thêm vào struct. Ngoài những khác biệt này, tôi không tìm thấy bất cứ điều gì đáng ngạc nhiên về chúng.


0

Tôi chỉ sử dụng struct khi tôi cần giữ một số dữ liệu mà không có bất kỳ chức năng thành viên nào liên quan đến nó (để hoạt động trên dữ liệu thành viên) và để truy cập trực tiếp vào các biến dữ liệu.

Ví dụ: Đọc / ghi dữ liệu từ các tệp và luồng ổ cắm, v.v. Truyền các đối số hàm trong một cấu trúc trong đó các đối số hàm quá nhiều và cú pháp hàm trông quá dài.

Về mặt kỹ thuật, không có sự khác biệt lớn giữa lớp và cấu trúc ngoại trừ khả năng truy cập mặc định. Hơn nữa nó phụ thuộc vào phong cách lập trình cách bạn sử dụng nó.


-4

Tôi nghĩ rằng Structs được dự định là một Cấu trúc dữ liệu (giống như một mảng thông tin loại đa dữ liệu) và các lớp được đặt cho Mã đóng gói (như các bộ sưu tập các chương trình con & hàm) ..

:


-6

Tôi không bao giờ sử dụng "struct" trong C ++.

Tôi không bao giờ có thể tưởng tượng một kịch bản mà bạn sẽ sử dụng một cấu trúc khi bạn muốn các thành viên riêng tư, trừ khi bạn cố tình gây nhầm lẫn.

Có vẻ như việc sử dụng các cấu trúc là một chỉ dẫn cú pháp về cách sử dụng dữ liệu, nhưng tôi chỉ muốn tạo một lớp và cố gắng làm cho nó rõ ràng trong tên của lớp hoặc thông qua các nhận xét.

Ví dụ

class PublicInputData {
    //data members
 };

Theo tôi, "chỉ dẫn cú pháp về cách sử dụng dữ liệu" là một lý do hoàn toàn chính đáng để sử dụng một cấu trúc, đặc biệt nếu phương án thay thế là sử dụng một nhận xét hoặc tên trong tên lớp.
Viktor Sehr

2
structTheo mặc định, sẽ không tuyên bố rằng các thành viên của lớp sẽ được công khai?
tên người dùng sai
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.