Sự khác biệt giữa struct và class trong C ++ là gì?


439

Câu hỏi này đã được hỏi trong ngữ cảnh của C # /. Net .

Bây giờ tôi muốn tìm hiểu sự khác biệt giữa một cấu trúc và một lớp trong C ++. Vui lòng thảo luận về sự khác biệt kỹ thuật cũng như lý do để chọn cái này hay cái khác trong thiết kế OO.

Tôi sẽ bắt đầu với một sự khác biệt rõ ràng:

  • Nếu bạn không chỉ định public:hoặc private:, các thành viên của cấu trúc được công khai theo mặc định; các thành viên của một lớp là riêng tư theo mặc định.

Tôi chắc chắn có những khác biệt khác được tìm thấy trong các góc tối của đặc tả C ++.


6
Liên kết này tóm tắt sự khác biệt tốt.
sjsam

1
Tại sao mọi người sử dụng struct để xây dựng một cây sau đó? Bởi vì dường như sự khác biệt không nhiều. BTW, Đó là một trang web tuyệt vời. @ Sjsam
JW.ZG

1
Tìm kiếm sự khác biệt giữa structtrong C và C ++? Xem ở đây .
Marc.2377

@ JW.ZG Không phải "tất cả" mọi người làm! Những người làm điều đó chỉ đơn giản là thích hoặc không nhận ra ý structnghĩa của C ++. ;) Nhưng không có lý do gì bạn không thể sử dụng classtừ khóa thay thế.
Các cuộc đua nhẹ nhàng trong quỹ đạo

Câu trả lời:


465

Bạn quên đi sự khác biệt thứ 2 khó khăn giữa các lớp và cấu trúc.

Bỏ tiêu chuẩn (§11.2.2 trong C ++ 98 đến C ++ 11):

Trong trường hợp không có trình xác định truy cập cho lớp cơ sở, công khai được giả sử khi lớp dẫn xuất được khai báo struct và private được giả sử khi lớp được khai báo lớp .

Và chỉ để hoàn thiện, sự khác biệt được biết đến rộng rãi hơn giữa lớp và struct được định nghĩa trong (11.2):

Thành viên của một lớp được xác định với lớp từ khóa là riêng tư theo mặc định. Các thành viên của một lớp được xác định với các từ khóa struct hoặc union được mặc định công khai .

Sự khác biệt bổ sung: từ khóa classcó thể được sử dụng để khai báo các tham số mẫu, trong khi structtừ khóa không thể được sử dụng.


22
Đó không thực sự là một sự khác biệt thứ hai, chỉ là câu hỏi đã nêu lên sự khác biệt không đầy đủ. Tất cả các tiểu dự án là riêng tư theo mặc định khi sử dụng class, công khai theo mặc định structvà cả hai đều xác định một loại lớp.
Ben Voigt

10
Tôi nghĩ rằng bạn đã bỏ lỡ điểm, Ben. Đó là sự kế thừa công khai cho các cấu trúc và riêng tư cho các lớp. Đó là một sự khác biệt rất quan trọng và hoàn toàn không liên quan đến việc truy cập thành viên thực tế. Ví dụ, ngôn ngữ rất có thể đã định nghĩa nó theo cách khác, ví dụ cả hai đều được kế thừa công khai theo mặc định và bạn sẽ có những hàm ý rất khác nhau.
Assaf Lavie

104
Trên thực tế, sự khác biệt khó khăn thực sự giữa structclasslà cái sau có thể được sử dụng thay cho a typenameđể khai báo một tham số mẫu, trong khi cái trước không thể. :)
sbi

21
@MrUniverse: Điều này là hoàn toàn sai. (Có một trường sử dụng điều này cho một hội nghị, nhưng nó không được thực thi về mặt cú pháp.)
sbi

3
@sbi "sự khác biệt khó khăn thực sự giữa struct và class" - dễ thương, nhưng câu hỏi là về sự khác biệt giữa một struct và một lớp, không phải về sự khác biệt trong các từ khóa có thể được sử dụng.
Jim Balter

161

Trích dẫn Câu hỏi thường gặp về C ++ ,

[7.8] Sự khác biệt giữa các từ khóa struct và class là gì?

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.

Cấu trúc và lớp 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.


123

Thật đáng để ghi nhớ nguồn gốc của C ++ và khả năng tương thích với C.

C có cấu trúc, nó không có khái niệm đóng gói, vì vậy mọi thứ đều công khai.

Mặc định công khai thường được coi là một ý tưởng tồi khi thực hiện một cách tiếp cận hướng đối tượng, vì vậy, trong việc tạo ra một dạng C có lợi cho OOP (bạn có thể thực hiện OO trong C, nhưng nó sẽ không giúp bạn) ý tưởng trong C ++ (ban đầu là "C With Classes"), mặc định làm cho các thành viên riêng tư theo mặc định.

Mặt khác, nếu Stroustrup đã thay đổi ngữ nghĩa của struct để các thành viên của nó được mặc định là riêng tư, thì nó sẽ bị hỏng tính tương thích (nó không còn đúng như các tiêu chuẩn được chuyển hướng, nhưng tất cả các chương trình C hợp lệ cũng là các chương trình C ++ hợp lệ, có ảnh hưởng lớn đến việc tạo cho C ++ một chỗ đứng).

Vì vậy, một từ khóa mới, classđược giới thiệu là chính xác như một cấu trúc, nhưng theo mặc định.

Nếu C ++ xuất phát từ đầu, không có lịch sử, thì có lẽ nó chỉ có một từ khóa như vậy. Nó cũng có thể sẽ không tạo ra tác động.

Nói chung, mọi người sẽ có xu hướng sử dụng struct khi họ đang làm một cái gì đó như cách các cấu trúc được sử dụng trong C; Các thành viên công cộng, không có nhà xây dựng (miễn là không liên kết với nhau, bạn có thể có các nhà xây dựng trong các cấu trúc, giống như với các lớp, nhưng mọi người có xu hướng không), không có phương thức ảo, v.v. mọi người đọc mã như để hướng dẫn các máy móc (hoặc nếu không chúng tôi sẽ gắn bó với mã op lắp ráp và VM thô), đó là một ý tưởng tốt để gắn bó với điều đó.


Có lẽ cũng đáng lưu ý rằng có lẽ dễ dàng hơn khi các lớp và cấu trúc hoạt động giống nhau dưới mui xe, hơn là về cơ bản chúng khác nhau. Có thể nhìn lại đã có một số lợi ích để ví dụ: chỉ định rằng mọi thứ được khai báo là cấu trúc phải là PODS (nghĩa là cấm các cấu trúc có thành viên ảo, các hàm tạo hoặc hàm hủy mặc định không tầm thường, v.v.) nhưng điều đó không phải là kiến ​​thức của tôi từng được yêu cầu bởi bất kỳ tiêu chuẩn C ++ cũng như việc thực hiện.
supercat

1
@supercat thực tế rằng đó là một ngôn ngữ OO trong đó một số lượng lớn các chương trình được viết bằng ngôn ngữ không phải OO là các chương trình hợp lệ, đưa khái niệm này trở nên nổi bật và dường như nó xuất hiện nhiều hơn ở các ngôn ngữ OO thuần túy hơn (và tất nhiên là thực sự được xác định trong tiêu chuẩn). Lịch sử của C ++ sớm chắc chắn giải thích rất nhiều về nó. "Thiết kế và tiến hóa của C ++" của Stroustrup là một tác phẩm thú vị.
Jon Hanna

1
Tôi nhận thấy một cuộc chiến tôn giáo giữa những người cảm thấy rằng mọi thứ không phải là "oop-ish", và những người nghĩ rằng OOP nên được coi là một công cụ, nhưng không phải công cụ. C ++ dường như chấp nhận triết lý sau này, nhưng tôi thực sự không biết nhiều về ngôn ngữ trước nó. Triết lý của riêng tôi là khi muốn có một đối tượng, người ta nên sử dụng một đối tượng và khi muốn có một tập hợp các biến độc lập nhưng có liên quan, người ta nên sử dụng nó. C ++ không phân biệt cú pháp giữa các loại điều đó và .NET cố gắng làm mờ sự khác biệt đó, nhưng tôi biết rất ít về D ...
supercat 16/12/13

1
... gợi ý rằng nó nhận ra nó so với C ++ hoặc .NET. Tập hợp các biến không chính xác là OOPish, nhưng điều đó không có nghĩa là chúng không nên được sử dụng khi chúng hữu ích .
supercat

3
Tôi không đồng ý với "C có cấu trúc, nó không có khái niệm đóng gói, vì vậy mọi thứ đều công khai.", Bạn có thể ẩn định nghĩa của structmột *.c-File và để các đơn vị dịch thuật khác chỉ sử dụng nó với một con trỏ. Vì vậy, bạn có một đóng gói thậm chí còn mạnh mẽ hơn, bởi vì các đơn vị dịch thuật khác thậm chí không biết những gì bên trong struct.
12431234123412341234123

32

Các thành viên của lớp được mặc định là riêng tư. Các thành viên của Struct được mặc định công khai. Bên cạnh đó không có sự khác biệt nào khác. Cũng xem câu hỏi này .


15
Không chỉ các thành viên, mà tất cả các quyền truy cập, bao gồm cả thừa kế.
Nemanja Trifunovic

4
Chà, tôi muốn nói sự khác biệt khác là ngữ nghĩa. Cấu trúc đối với nhiều người khiến họ nghĩ rằng "cấu trúc dữ liệu" là phần còn lại từ C.
Kris Kumler

3
@KrisKumler: Đó không phải là "ngữ nghĩa"; họ là những cảm xúc cá nhân. Cả hai structclasstuyên bố một lớp với ngữ nghĩa giống hệt nhau (mặc dù giải thích phân tích cú pháp khôn ngoan của cơ thể định nghĩa).
Các cuộc đua nhẹ nhàng trong quỹ đạo

28

Theo Stroustrup trong ngôn ngữ lập trình C ++ :

Phong cách bạn sử dụng phụ thuộc vào hoàn cảnh và hương vị. Tôi thường thích sử dụng structcho các lớp có tất cả dữ liệu công khai. Tôi nghĩ về các lớp như "các loại không hoàn toàn đúng, chỉ là các cấu trúc dữ liệu."

Về mặt chức năng, không có sự khác biệt nào ngoài công khai / riêng tư


32
Khác nhau cái gì? Vui lòng giải thích.
crashmstr

10

CẤU TRÚC là một loại Kiểu dữ liệu trừu tượng phân chia một đoạn bộ nhớ nhất định theo đặc tả cấu trúc. Các cấu trúc đặc biệt hữu ích trong việc tuần tự hóa / giải tuần tự tệp vì cấu trúc thường có thể được ghi vào nguyên văn của tệp. (tức là Lấy một con trỏ tới struct, sử dụng macro SIZE để tính số byte để sao chép, sau đó di chuyển dữ liệu vào hoặc ra khỏi struct.)

Các lớp là một loại khác nhau của kiểu dữ liệu trừu tượng cố gắng đảm bảo ẩn thông tin. Trong nội bộ, có thể có nhiều loại máy móc, phương pháp, biến tạm thời, biến trạng thái. v.v ... tất cả được sử dụng để trình bày một API nhất quán cho bất kỳ mã nào muốn sử dụng lớp.

Trong thực tế, các cấu trúc là về dữ liệu, các lớp là về mã.

Tuy nhiên, bạn cần phải hiểu rằng đây chỉ là những điều trừu tượng. Hoàn toàn có thể tạo ra các cấu trúc trông rất giống các lớp và các lớp trông rất giống các cấu trúc. Trên thực tế, các trình biên dịch C ++ sớm nhất chỉ là các trình biên dịch trước dịch mã C ++ sang C. Do đó, các tóm tắt này là một lợi ích cho tư duy logic, không nhất thiết phải là một tài sản cho chính máy tính.

Ngoài thực tế là mỗi loại là một kiểu trừu tượng khác nhau, Các lớp cung cấp các giải pháp cho câu đố đặt tên mã C. Vì bạn không thể có nhiều hơn một hàm được hiển thị cùng tên, nên các nhà phát triển đã sử dụng theo mẫu _ (). ví dụ mathlibext tối_max (). Bằng cách nhóm các API thành các lớp, các hàm tương tự (ở đây chúng tôi gọi chúng là "phương thức") có thể được nhóm lại với nhau và được bảo vệ khỏi việc đặt tên phương thức trong các lớp khác. Điều này cho phép lập trình viên tổ chức mã của mình tốt hơn và tăng tái sử dụng mã. Về lý thuyết, ít nhất.


1
Đây là điều không rõ ràng nhất về cấu trúc và các lớp. "Cấu trúc là về dữ liệu, các lớp là về mã" có thể được chia sẻ lại thành "các cấu trúc là về dữ liệu, các lớp là về dữ liệu, bảo mật và các hoạt động được thực hiện trên dữ liệu này"
Arun Aravind

3
Không thể tạo cấu trúc trong C ++. Chỉ có thể tạo một lớp bằng cách sử dụng structtừ khóa được kế thừa .
Các cuộc đua nhẹ nhàng trong quỹ đạo

1
Câu trả lời này dường như không phải là về C ++. Trong C ++, structkhai báo các lớp (bao gồm public/ private/ protected, thừa kế, v.v.).
melpomene

Làm thế nào là cấu trúc trừu tượng? Viết các cấu trúc thô vào một tệp có nhiều vấn đề ngay cả trong C (các vấn đề thông thường bao gồm đệm, endian, kích thước từ khác nhau, v.v.). SIZEMacro này bạn đang nói về cái gì?
melpomene

10

1) Các thành viên của một lớp là riêng tư theo mặc định và các thành viên của struct được công khai theo mặc định.

Ví dụ chương trình 1 không thành công trong việc biên dịch và chương trình 2 hoạt động tốt.

// Program 1
#include <stdio.h>

class Test {
    int x; // x is private
};
int main()
{
  Test t;
  t.x = 20; // compiler error because x is private
  getchar();
  return 0;
}
Run on IDE
// Program 2
#include <stdio.h>

struct Test {
    int x; // x is public
};
int main()
{
  Test t;
  t.x = 20; // works fine because x is public
  getchar();
  return 0;
}

2) Khi lấy một cấu trúc từ một lớp / struct, bộ xác định truy cập mặc định cho một lớp / struct cơ sở là công khai. Và khi lấy một lớp, trình xác định truy cập mặc định là riêng tư.

Ví dụ chương trình 3 không thành công trong việc biên dịch và chương trình 4 hoạt động tốt.

// Program 3
#include <stdio.h>

class Base {
public:
    int x;
};

class Derived : Base { }; // is equilalent to class Derived : private Base {}

int main()
{
  Derived d;
  d.x = 20; // compiler error becuase inheritance is private
  getchar();
  return 0;
}
Run on IDE
// Program 4
#include <stdio.h>

class Base {
public:
    int x;
};

struct Derived : Base { }; // is equilalent to struct Derived : public Base {}

int main()
{
  Derived d;
  d.x = 20; // works fine becuase inheritance is public
  getchar();
  return 0;
}

Tôi đã xóa các ví dụ mã 3- 7 như các chuyên gia đã đề cập
Suraj K Thomas

8

Sự khác biệt duy nhất khác là sự kế thừa mặc định của các lớp và cấu trúc, mà, không ngạc nhiên, là riêng tư và công khai tương ứng.


5
  1. Các thành viên của một cấu trúc được công khai theo mặc định, các thành viên của lớp là riêng tư theo mặc định.
  2. Kế thừa mặc định cho Cấu trúc từ một cấu trúc hoặc lớp khác là công khai. Kế thừa lỗi cho lớp từ cấu trúc hoặc lớp khác là riêng tư.
class A{    
public:    
    int i;      
};

class A2:A{    
};

struct A3:A{    
};


struct abc{    
    int i;
};

struct abc2:abc{    
};

class abc3:abc{
};


int _tmain(int argc, _TCHAR* argv[])
{    
    abc2 objabc;
    objabc.i = 10;

    A3 ob;
    ob.i = 10;

    //A2 obja; //privately inherited
    //obja.i = 10;

    //abc3 obss;
    //obss.i = 10;
}

Đây là trên VS2005.


_tmainkhông phải là C ++ chuẩn.
melpomene

4

Không có trong đặc điểm kỹ thuật, không. Sự khác biệt chính là kỳ vọng của lập trình viên khi họ đọc mã của bạn sau 2 năm. cấu trúc thường được coi là POD. Cấu trúc cũng được sử dụng trong siêu lập trình mẫu khi bạn xác định loại cho các mục đích khác ngoài việc xác định đối tượng.


4

Một điều khác cần lưu ý, nếu bạn cập nhật một ứng dụng cũ có cấu trúc để sử dụng các lớp, bạn có thể gặp phải vấn đề sau:

Mã cũ có cấu trúc, mã đã được dọn sạch và chúng được đổi thành các lớp. Một hoặc hai hàm ảo sau đó đã được thêm vào lớp cập nhật mới.

Khi các hàm ảo nằm trong các lớp thì bên trong trình biên dịch sẽ thêm con trỏ bổ sung vào dữ liệu lớp để trỏ đến các hàm.

Làm thế nào điều này sẽ phá vỡ mã kế thừa cũ là nếu trong mã cũ ở đâu đó, cấu trúc đã bị xóa bằng cách sử dụng memfill để xóa tất cả thành số không, điều này cũng sẽ làm hỏng dữ liệu con trỏ thêm.


1
Mã sử ​​dụng memfill để xóa cấu trúc có thể có các thói quen tấn công khác. Đi thận trọng.
David Thornley

@DavidThornley: Sử dụng một điền không để xóa hoặc khởi tạo một cấu trúc dữ liệu là tiêu chuẩn trong C. Trong một dự án hỗn hợp ngôn ngữ, người ta không thể mong đợi các mã trong phần C để tránh callocủng hộ new. Tất cả những gì có thể làm là cố gắng đảm bảo rằng bất kỳ cấu trúc nào được sử dụng bởi phần C của mã trên thực tế là PODS.
supercat

4
  1. Thành viên của một lớp được định nghĩa với từ khóa classprivatetheo mặc định. Các thành viên của một lớp được xác định bằng các từ khóa struct(hoặc union) publictheo mặc định.

  2. Trong trường hợp không có trình xác định truy cập cho lớp cơ sở, publicđược giả sử khi lớp dẫn xuất được khai báo structprivateđược giả sử khi lớp được khai báo class.

  3. Bạn có thể khai báo một enum classnhưng không phải là một enum struct.

  4. Bạn có thể sử dụng template<class T>nhưng không template<struct T>.

Cũng lưu ý rằng tiêu chuẩn C ++ cho phép bạn khai báo trước một loại là a struct, sau đó sử dụng classkhi khai báo loại và ngược lại. Ngoài ra, std::is_class<Y>::valuetruecho Y là một structvà một class, nhưng là falsemột enum class.


câu trả lời hay, mặc dù tôi thiếu một điều rõ ràng không thể nhầm lẫn 0) sự khác biệt giữa structclasstrong c ++ là sự khác biệt giữa các từ khóa, không phải giữa các loại dữ liệu (hoặc một số thay thế tốt hơn;)
idclev 463035818

@ trước đây là Unknown_463035818: Nhưng bạn có nghĩ std::is_class<Y>::valuerằng điều đó không?
Bathsheba

vâng, chỉ nghĩ rằng nó có thể nổi bật hơn, bởi vì đó là sự hiểu lầm phổ biến và một khi đó là cách khác, phần còn lại chỉ là hệ quả.
idclev 463035818

Không bao giờ, câu trả lời của bạn là hoàn hảo, tôi đã viết một câu khác, không đau để có thêm một câu nữa
idclev 463035818

4

Sự khác biệt giữa classstructlà sự khác biệt giữa các từ khóa, không phải giữa các loại dữ liệu. Hai cái này

struct foo : foo_base { int x;};
class bar : bar_base { int x; };

cả hai đều xác định một loại lớp. Sự khác biệt của các từ khóa trong ngữ cảnh này là quyền truy cập mặc định khác nhau:

  • foo::xlà công khai và foo_baseđược kế thừa công khai
  • bar::xlà riêng tư và bar_baseđược thừa kế tư nhân

2

Đây là một lời giải thích tốt: http://carcino.gen.nz/tech/cpp/struct_vs_group.php

Vì vậy, một lần nữa: trong C ++, một cấu trúc giống hệt với một lớp ngoại trừ các thành viên của một cấu trúc có khả năng hiển thị công khai theo mặc định, nhưng các thành viên của một lớp có mặc định riêng tư theo mặc định.


2

Đó chỉ là một quy ước. Các cấu trúc có thể được tạo để giữ dữ liệu đơn giản nhưng sau đó sẽ phát triển thời gian với việc bổ sung các hàm thành viên và hàm tạo. Mặt khác, thật bất thường khi thấy bất cứ điều gì khác ngoài công khai: truy cập trong một cấu trúc.


2

ISO IEC 14882-2003

9 lớp

§3

Một cấu trúc là một lớp được định nghĩa bằng khóa lớp struct ; Các thành viên và các lớp cơ sở của nó (khoản 10) được công khai theo mặc định (điều 11).


2

Một sự khác biệt chính là khi nói đến Mẫu. Theo tôi biết, bạn có thể sử dụng một lớp khi bạn xác định một mẫu nhưng KHÔNG phải là một cấu trúc.

template<class T> // OK
template<struct T> // ERROR, struct not allowed here

1
Nếu bạn có ý định nhấn mạnh rằng các cấu trúc không thể được sử dụng như các kiểu tổng quát, thì bạn đã nhầm. Và structkhông được phép ở đó chỉ theo quy ước (tốt hơn là classtừ khóa được sử dụng theo nghĩa khác ở đây, xem Sử dụng 'lớp' hoặc 'kiểu chữ' cho các tham số mẫu ).
dma_k

Từ khóa không được phép ở đó, nhưng bạn có thể vượt qua trong một lớp bạn đã xác định structtốt. Đơn giản hãy thử nó. struct T{}; template <typename T> void foo() {} foo<T>();
Các cuộc đua nhẹ nhàng trong quỹ đạo

1

Các câu trả lời khác đã đề cập đến các mặc định riêng tư / công khai, (nhưng lưu ý rằng một cấu trúc là một lớp là một cấu trúc; chúng không phải là hai mục khác nhau, chỉ là hai cách định nghĩa cùng một mục).

Điều thú vị cần lưu ý (đặc biệt là khi người hỏi có khả năng sử dụng MSVC ++ vì anh ta đề cập đến C ++ "không được quản lý") là Visual C ++ phàn nàn trong một số trường hợp nếu một lớp được khai báo classvà sau đó được định nghĩa bằng struct(hoặc có thể theo cách khác ), mặc dù tiêu chuẩn nói rằng đó là hoàn toàn hợp pháp.


Tôi biết đó là một nhận xét rất muộn, nhưng lưu ý rằng cảnh báo đã nói ở trên không phải là không có giá trị vì các cấu trúc và lớp của Windows ABI khác nhau và do đó việc trộn các khai báo của lớp và cấu trúc thực sự có thể dẫn đến khó hiểu các vấn đề liên kết!
MFH

1
  • . Trong các lớp, tất cả các thành viên theo mặc định là riêng tư nhưng trong cấu trúc, các thành viên được mặc định công khai.

    1. Không có thuật ngữ như hàm tạo và hàm hủy cho các cấu trúc, nhưng đối với trình biên dịch lớp sẽ tạo mặc định nếu bạn không cung cấp.

    2. Cấu trúc trống Sizeof là 0 Byte wer vì lớp trống Sizeof là 1 Byte Kiểu truy cập mặc định của cấu trúc là công khai. Một cấu trúc thường được sử dụng để nhóm dữ liệu.

    Kiểu truy cập mặc định của lớp là riêng tư và chế độ mặc định cho kế thừa là riêng tư. Một lớp nên được sử dụng để nhóm dữ liệu và phương thức hoạt động trên dữ liệu đó.

    Nói tóm lại, quy ước là sử dụng struct khi mục đích là nhóm dữ liệu và sử dụng các lớp khi chúng ta yêu cầu trừu tượng hóa dữ liệu và, có lẽ là kế thừa.

    Trong các cấu trúc và các lớp C ++ được truyền theo giá trị, trừ khi được tham chiếu rõ ràng. Trong các ngôn ngữ khác, các lớp và cấu trúc có thể có ngữ nghĩa riêng biệt - tức là. các đối tượng (thể hiện của các lớp) có thể được truyền bằng tham chiếu và các cấu trúc có thể được truyền theo giá trị. Lưu ý: Có ý kiến ​​liên quan đến câu hỏi này. Xem trang thảo luận để thêm cuộc trò chuyện.


3
"2. Cấu trúc trống của Sizeof là 0 Byte wer vì lớp trống Sizeof là 1 Byte". Sai. Tôi vừa thử nghiệm với g++. Bạn có thể nghĩ về Tối ưu hóa cơ sở trống, nhưng điều đó cũng áp dụng cho cả hai.
cdunn2001

1
Không đúng. Trong C ++ kích thước của một cấu trúc trống là 1. Trong C, một cấu trúc trống không được phép. GCC cho phép các cấu trúc trống trong C làm phần mở rộng trình biên dịch và cấu trúc như vậy có kích thước 0.
Johan Råde

Câu trả lời này là sai. Ngoài điều kích thước, phần xây dựng / phần hủy cũng không chính xác: các cấu trúc có thể có các hàm tạo và hàm hủy tốt. Trong thực tế, structtạo các lớp đầy đủ trong C ++.
melpomene

1

Mặc dù ngụ ý bởi các câu trả lời khác, nó không được đề cập rõ ràng - các cấu trúc đó tương thích với C, tùy thuộc vào cách sử dụng; lớp học thì không.

Điều này có nghĩa là nếu bạn đang viết một tiêu đề mà bạn muốn tương thích với C thì bạn không có tùy chọn nào khác ngoài struct (trong thế giới C không thể có chức năng; nhưng có thể có con trỏ hàm).


-1

Bạn có thể cân nhắc điều này để biết hướng dẫn khi nào nên đi theo cấu trúc hoặc lớp, https://msdn.microsoft.com/en-us/l Library / ms229017% 28v = vs.110% 29.aspx .

NGƯỜI TIÊU DÙNG định nghĩa một cấu trúc thay vì một lớp nếu các thể hiện của loại này nhỏ và thường tồn tại trong thời gian ngắn hoặc thường được nhúng trong các đối tượng khác.

X AVOID xác định cấu trúc trừ khi loại có tất cả các đặc điểm sau:

Nó đại diện một cách hợp lý một giá trị duy nhất, tương tự như các kiểu nguyên thủy (int, double, v.v.).

Nó có kích thước cá thể dưới 16 byte.

Nó là bất biến.

Nó sẽ không phải được đóng hộp thường xuyên.


Đó là về .NET / C #, không phải C ++.
melpomene

-2

Lớp học chỉ có ý nghĩa trong bối cảnh kỹ thuật phần mềm. Trong bối cảnh cấu trúc dữ liệu và thuật toán, lớp và cấu trúc không khác nhau. Không có bất kỳ quy tắc nào bị hạn chế rằng thành viên của lớp phải được tham chiếu.

Khi phát triển dự án lớn với hàng tấn người không có lớp, cuối cùng bạn có thể nhận được mã ghép phức tạp vì mọi người đều sử dụng bất kỳ chức năng và dữ liệu nào họ muốn. lớp cung cấp các điều khiển và quyền thừa kế để tăng cường mã tách và tái sử dụng.

Nếu bạn đọc một số nguyên tắc kỹ thuật phần mềm, bạn sẽ thấy hầu hết các tiêu chuẩn không thể được thực hiện dễ dàng nếu không có lớp. ví dụ: http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29

BTW, Khi một cấu trúc phân bổ một bộ nhớ và bao gồm một số biến, các biến loại giá trị chỉ ra rằng các giá trị được đặt trong đó cấu trúc được phân bổ. Ngược lại, các giá trị của biến loại tham chiếu là bên ngoài và tham chiếu bởi một con trỏ cũng được nhúng vào nơi cấu trúc được phân bổ.


Câu trả lời này dường như không phải là về C ++. Trong C ++, structkhai báo các lớp (bao gồm các điều khiển quyền, kế thừa, v.v.).
melpomene

-3

Sự khác biệt giữa các từ khóa structclass trong C ++ là, khi không có chỉ định cụ thể về loại dữ liệu tổng hợp cụ thể thì theo mặc định struct hoặc union là các từ khóa công khai chỉ xem xét ẩn dữ liệu nhưng class là từ khóa riêng xem xét việc ẩn chương trình mã hoặc dữ liệu. Luôn luôn một số lập trình viên sử dụng struct cho dữ liệu và lớp cho mã sake. Để biết thêm thông tin liên hệ với các nguồn khác.


OP đã đề cập rằng structcác thành viên được công khai theo mặc định và câu trả lời được chấp nhận từ năm 2009 đề cập đến việc thừa kế. Tại sao viết một câu trả lời khác mà không thêm thông tin mới 4 năm sau?
melpomene

-3

Trong tất cả các yếu tố này, có thể kết luận rằng Lớp khái niệm rất phù hợp để đại diện cho các đối tượng trong thế giới thực chứ không phải là "Cấu trúc". Nói chung, vì các khái niệm OOP được sử dụng trong lớp rất thực tế trong việc giải thích các kịch bản trong thế giới thực do đó dễ dàng hợp nhất chúng với thực tế. Ví dụ, thừa kế mặc định là công khai cho các cấu trúc nhưng nếu chúng ta áp dụng quy tắc này cho thế giới thực thì thật nực cười. Nhưng trong một thừa kế mặc định của lớp là riêng tư thì thực tế hơn.

Dù sao, điều tôi cần biện minh là Class là một khái niệm áp dụng trong thế giới thực rộng hơn nhiều trong khi Cấu trúc là một Khái niệm nguyên thủy với tổ chức nội bộ kém (Eventhough struct tuân theo các khái niệm OOP, chúng có ý nghĩa kém)


1
Làm thế nào là thừa kế tư nhân "thực tế hơn"? Hầu hết các ngôn ngữ lập trình thậm chí không có khái niệm thừa kế riêng.
melpomene

-3

Sự khác biệt chính giữa cấu trúc và từ khóa lớp trong oops là, không có khai báo thành viên công khai và riêng tư nào có trong cấu trúc. Và chức năng thành viên dữ liệu và thành viên có thể được định nghĩa là công khai, riêng tư cũng như được bảo vệ.


Câu trả lời này dường như không phải là về C ++. Trong C ++, structkhai báo các lớp (bao gồm public/ private/ protected, thừa kế, v.v.).
melpomene

-3

** CẬP NHẬT: ** Hãy bỏ qua trả lời này. Tôi đã không xem xét khả năng đối với struct, giá trị này chưa được khởi tạo mà chỉ xảy ra là 0. Không có sự khác biệt khởi tạo giữa struct và class.


Tôi đang thấy một sự khác biệt khác giữa các cấu trúc và các lớp phải làm với khởi tạo mặc định.

struct Foo {
    int a;
};

class Bar {
    int a;
};

class Tester {
    Foo m_Foo = Foo();
    Bar m_Bar = Bar();

public:
    Tester() {}
};

int main() {
    auto myTester = Tester();
}

Chạy mã đó và kiểm tra myTester. Bạn sẽ thấy rằng đối với m_Foo, struct, m_Foo.a đã được khởi tạo thành 0, nhưng đối với m_Bar, lớp, m_Bar.a chưa được khởi tạo. Vì vậy, dường như có một sự khác biệt trong những gì mà hàm tạo mặc định làm cho struct so với class. Tôi đang thấy điều này với Visual Studio.


1
Làm thế nào bạn xác định m_Foo.ađược đã được khởi tạo? Điều gì xảy ra nếu nó chưa được khởi tạo và chỉ xảy ra 0?
melpomene

Uhhh, tôi đã không. Lỗi của tôi. Đây không phải là một sự khác biệt giữa struct và class. Đặc điểm khởi tạo là như nhau.
Eric Hill

-4

Sự khác biệt chính giữa struct và class là trong struct bạn chỉ có thể khai báo các biến dữ liệu của các loại dữ liệu khác nhau trong khi trong lớp bạn có thể khai báo các biến dữ liệu, các hàm thành viên và do đó bạn có thể thao tác các biến dữ liệu thông qua các hàm.

-> một điều tiện dụng khác mà tôi tìm thấy trong lớp vs struct là trong khi triển khai các tệp trong một chương trình nếu bạn muốn thực hiện một số hoạt động của một cấu trúc lặp đi lặp lại trên mỗi tập hợp hoạt động mới bạn cần thực hiện một chức năng riêng biệt và bạn cần phải truyền đối tượng của struct sau khi đọc nó từ tệp để thực hiện một số thao tác trên nó. trong khi ở trong lớp nếu bạn thực hiện một chức năng thực hiện một số thao tác trên dữ liệu cần thiết mọi lúc..thật dễ dàng, bạn chỉ cần đọc đối tượng từ tệp và gọi hàm ..

Nhưng nó phụ thuộc vào lập trình viên theo cách mà anh ấy / cô ấy thấy phù hợp ... theo tôi, tôi thích lớp mọi lúc chỉ vì nó hỗ trợ OOP và đó là lý do nó được triển khai trong hầu hết mọi ngôn ngữ và là tính năng tuyệt vời của lập trình mọi thời đại; - )

Và vâng, sự khác biệt không thể tha thứ nhất mà tôi quên đề cập đến là lớp hỗ trợ ẩn dữ liệu và cũng hỗ trợ các hoạt động được thực hiện trên các kiểu dữ liệu được xây dựng trong khi struct không!


1
Trong C ++ structcó thể có các chức năng thành viên
chtz

@chtz Cảm ơn ... tôi mới biết về tính năng này ngay bây giờ .. cảm ơn rất nhiều .. tôi chỉ là người mới bắt đầu không phải là chuyên gia như bạn nên trong tương lai cũng cần lời khuyên từ các bạn :-)
Yug Rawal

và thực sự, chức năng thành viên sẽ được dự định theo nghĩa rộng hơn của nó. structcó thể có các hàm tạo, hàm thành viên và hàm phân phối (có thể là ảo, có thể là riêng tư, được bảo vệ hoặc công khai). Họ có thể thừa kế và được thừa kế. thật ra ... mọi thứ mà một lớp có thể có. một quy ước có tính chất là khai báo với struct những gì bạn đã khai báo là struct trong C và là lớp nếu chúng ta khai báo biến riêng và biến được bảo vệ, các hàm ảo, ctor và dtor, v.v. Nhưng đó chỉ là một quy ước, không được thi hành bởi ngôn ngữ
Gian Paolo

-5

Tôi tìm thấy một sự khác biệt khác. nếu bạn không định nghĩa hàm tạo trong một lớp, trình biên dịch sẽ định nghĩa một hàm tạo. nhưng trong một cấu trúc nếu bạn không định nghĩa một hàm tạo, trình biên dịch cũng không định nghĩa một hàm tạo. Vì vậy, trong một số trường hợp chúng tôi thực sự không cần một nhà xây dựng, struct là một lựa chọn tốt hơn (mẹo hiệu suất). và xin lỗi vì tiếng Anh của tôi không tốt


4
Đây không phải là sự thật. Không có sự khác biệt giữa một lớp được xác định với structtừ khóa và một lớp được xác định với classtừ khóa về mặt này.
ymett

Khi tôi sử dụng một cấu trúc mà không có hàm tạo, tôi có tốc độ tốt hơn một lớp không có hàm tạo.
Ali


-5

Các lớp là các kiểu tham chiếu và các cấu trúc là các kiểu giá trị.
Khi tôi nói Classes là kiểu tham chiếu,
về cơ bản chúng sẽ chứa địa chỉ của một biến thể hiện.

Ví dụ:

Class MyClass
{
    Public Int DataMember;  //By default, accessibility of class data members 
                            //will be private. So I am making it as Public which 
                            //can be accessed outside of the class.
}

Trong phương thức chính,
tôi có thể tạo một thể hiện của lớp này bằng toán tử mới phân bổ bộ nhớ cho lớp này
và lưu địa chỉ cơ sở của biến đó vào biến loại MyClass (_myClassObject2).

Static Public void Main (string[] arg)
{
    MyClass _myClassObject1 = new MyClass();
    _myClassObject1.DataMember = 10;

    MyClass _myClassObject2 = _myClassObject1;
    _myClassObject2.DataMember=20;
}

Trong chương trình trên, MyClass _myClassObject2 = _myClassObject1; hướng dẫn chỉ ra rằng cả hai biến kiểu MyClass

  1. myClassObject1
  2. myClassObject2

và sẽ trỏ đến cùng một vị trí bộ nhớ.
Về cơ bản, nó gán cùng một vị trí bộ nhớ vào một biến khác cùng loại.

Vì vậy, nếu bất kỳ thay đổi nào chúng ta thực hiện trong bất kỳ một trong các đối tượng loại MyClass sẽ có ảnh hưởng đến một đối tượng khác
vì cả hai đều trỏ đến cùng một vị trí bộ nhớ.

"_myClassObject1.DataMember = 10;" tại dòng này cả thành viên dữ liệu của đối tượng sẽ chứa giá trị 10.
"_myClassObject2.DataMember = 20;" tại dòng này cả thành viên dữ liệu của đối tượng sẽ chứa giá trị 20.
Cuối cùng, chúng ta đang truy cập các bảng dữ liệu của một đối tượng thông qua các con trỏ.

Không giống như các lớp, cấu trúc là các loại giá trị. Ví dụ:

Structure MyStructure
{
    Public Int DataMember;  //By default, accessibility of Structure data 
                            //members will be private. So I am making it as 
                            //Public which can be accessed out side of the structure.
}

Static Public void Main (string[] arg)
{
    MyStructure _myStructObject1 = new MyStructure();
    _myStructObject1.DataMember = 10;

    MyStructure _myStructObject2 = _myStructObject1;
    _myStructObject2.DataMember = 20;
}

Trong chương trình trên,
khởi tạo đối tượng của kiểu
MyStr struct bằng cách sử dụng toán tử mới và lưu địa chỉ vào biến _myStabaseObject của loại MyStr struct và
gán giá trị 10 cho thành viên dữ liệu của cấu trúc bằng cách sử dụng "_mySturationObject1.DataMember = 10".

Trong dòng tiếp theo,
tôi đang khai báo một biến khác _myStabaseObject2 thuộc loại MyStr struct và gán _mySturationObject1 vào đó.
Ở đây trình biên dịch .NET C # tạo một bản sao khác của đối tượng _myStr structObject1 và
gán vị trí bộ nhớ đó vào biến MyStr struct _mySturationObject2.

Vì vậy, bất kỳ thay đổi nào chúng tôi thực hiện trên _myStabaseObject1 sẽ không bao giờ có ảnh hưởng đến một biến khác _mySturationObject2 của loại MyStabaserue.
Đó là lý do tại sao chúng ta đang nói Cấu trúc là loại giá trị.

Vì vậy, lớp Cơ sở trực tiếp cho lớp là Đối tượng và Lớp Cơ sở ngay lập tức cho Cấu trúc là ValueType kế thừa từ Đối tượng.
Các lớp sẽ hỗ trợ Kế thừa trong khi Cấu trúc sẽ không.

Làm thế nào chúng ta nói điều đó?
Và lý do đằng sau đó là gì?
Câu trả lời là Lớp học.

Nó có thể là trừu tượng, niêm phong, tĩnh và một phần và không thể là Riêng tư, Được bảo vệ và bảo vệ nội bộ.


4
Tôi nghĩ rằng điều này đang cố gắng trả lời câu hỏi cho c #? Câu hỏi là về c ++, và điều đó làm cho câu trả lời này không chính xác, phải không?
smw

@smw hoàn toàn, anh ấy đã viết mã mẫu của mình bằng C # và tôi đã đến đây để kiểm tra xem có sự khác biệt nào về thông số truyền giữa C ++ structclass. Không ai ở đây đã đề cập đến nó, cũng như toàn bộ web. Vì vậy, tôi cũng không nghĩ điều này áp dụng cho C ++.
John

Điều này thậm chí không hợp lệ mã C # - các từ khóa đều sai. "Công khai", "Tĩnh", "Int" và "Lớp" không nên được viết hoa và nó phải là "struct" chứ không phải "Architecture". Mô tả hầu hết là chính xác cho C # (mặc dù các cấu trúc vẫn có thể kế thừa giao diện, không phải các cấu trúc khác), nhưng không trả lời câu hỏi vì đó là về C ++ ...
Darrel Hoffman

2
Câu trả lời này là hoàn toàn vô nghĩa. Nó sử dụng một hỗn hợp lạ của Visual Basic và C # cho các ví dụ mã của nó và toàn bộ "Các lớp là kiểu tham chiếu và Cấu trúc là kiểu giá trị" ... điều này chỉ áp dụng cho .NET (tức là C #) không áp dụng cho C ++. Anh đang ở nhầm phòng, anh bạn. Đây là nơi bạn thuộc về: stackoverflow.com/questions/13049
TheFlash

Nhưng câu trả lời này chỉ ra điều tương tự là hợp lệ đối với C (++), rằng các cấu trúc được sử dụng như các loại giá trị. int a = 3; int b = a;và tương tựMyStruct a=MyStruct("data"); MyStruct b = a;
luckydonald

-8

Có 3 sự khác biệt cơ bản giữa cấu trúc và lớp

Bộ nhớ 1St được dành riêng cho cấu trúc trong bộ nhớ ngăn xếp (gần với ngôn ngữ lập trình) cho dù lớp trong bộ nhớ ngăn xếp chỉ được dành riêng cho bộ nhớ và bộ nhớ thực được dành riêng trong bộ nhớ heap.

2Nd - Theo mặc định, cấu trúc được coi là công khai cho dù lớp coi là riêng tư.

3Rd- không thể sử dụng lại mã trong cấu trúc nhưng trong lớp chúng ta có thể sử dụng lại cùng một mã trong nhiều thời gian được gọi là vô sinh


2
Các cấu trúc C ++ hỗ trợ kế thừa và các phương thức trừu tượng. Cấu trúc và lớp được phân bổ theo cùng một cách. Phân bổ lớp trên heap ngay cả khi chúng không được khởi tạo bằng "mới" không có ý nghĩa đối với các hệ thống nhúng.
JCMS

2
# 1 cũng sai. Ngăn xếp được sử dụng khi bạn khai báo một loại nào đó là biến cục bộ và heap được sử dụng khi bạn sử dụng toán tử "mới".
Score_Under
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.