2009-01-08 21 views
41

Nếu tôi có một lớp như sauCấu trúc của một C++ Object trong Memory Vs một Struct

class Example_Class 
    { 
     private: 
     int x; 
     int y; 
     public: 
     Example_Class() 
     { 
      x = 8; 
      y = 9; 
     } 
     ~Example_Class() 
     { } 
    }; 

Và một struct như sau

struct 
{ 
    int x; 
    int y; 
} example_struct; 

là cấu trúc trong bộ nhớ của example_struct simmilar đó trong Example_Class

ví dụ: nếu tôi làm như sau

struct example_struct foo_struct; 
Example_Class foo_class = Example_Class(); 

memcpy(&foo_struct, &foo_class, sizeof(foo_struct)); 

sẽ foo_struct.x = 8foo_struct.y = 9 (ví dụ: giá trị giống với giá trị x, y trong foo_class)?

Lý do tôi hỏi là tôi có thư viện C++ (không muốn thay đổi nó) đang chia sẻ một đối tượng với mã C và tôi muốn sử dụng cấu trúc để biểu diễn đối tượng đến từ thư viện C++. Tôi chỉ quan tâm đến các thuộc tính của đối tượng.

Tôi biết tình huống lý tưởng sẽ có lớp bọc Example_class tạo một cấu trúc chung giữa mã C và C++ nhưng sẽ không dễ dàng thay đổi thư viện C++ đang sử dụng.

+5

Chỉ cần một bình luận nhỏ, nhà xây dựng của bạn có thể (và một số nói nên) được viết như thế này: Example_Class(): x (8), y (9) {} – Dan

Trả lời

61

C++ chuẩn đảm bảo rằng bố trí bộ nhớ của một C struct và C++ class (hoặc struct - cùng điều) sẽ giống nhau, với điều kiện C++ class/struct phù hợp với tiêu chí là POD ("Dữ liệu cũ thuần túy"). Vậy POD có nghĩa là gì?

Một lớp học hoặc struct là POD nếu:

  • Tất cả các thành viên dữ liệu là công khai và tự POD hay cơ bản các loại (nhưng không tham khảo hoặc các loại con trỏ-to-thành viên), hoặc các mảng như vậy
  • Nó không có nhà xây dựng người dùng định nghĩa, các nhà khai thác chuyển nhượng hoặc hủy
  • Nó không có chức năng ảo
  • Nó không có lớp cơ sở

Chỉ cho phép "C++ - isms" là các hàm thành viên không phải là ảo, các thành viên tĩnh và các hàm thành viên.

Vì lớp của bạn có cả hàm tạo và hàm hủy, nên chính thức nói không thuộc loại POD, do đó đảm bảo không giữ. (Mặc dù, như những người khác đã đề cập, trong thực tế hai bố cục có thể giống hệt nhau trên bất kỳ trình biên dịch nào mà bạn thử, miễn là không có chức năng ảo).

Xem phần [26.7] của C++ FAQ Lite để biết thêm chi tiết.

+2

Vì anh ta đang sử dụng một thư viện riêng biệt, tôi cho rằng sự khác biệt trong cài đặt liên kết cấu trúc trình biên dịch có thể tồn tại khi thư viện được biên dịch có thể gây ra sự khác biệt về bố cục bộ nhớ. Không có khả năng, nhưng có thể, có vẻ như. – moodboom

10

là cấu trúc trong bộ nhớ của simmilar example_struct như trong Example_Class

Các hành vi không được bảo đảm, và là biên dịch phụ thuộc.

Có nói rằng, câu trả lời là "có, trên máy của tôi", miễn là Example_Class không chứa phương thức ảo (và không kế thừa từ một lớp cơ sở).

+0

Tôi biết tôi có lẽ không nên làm giải pháp phụ thuộc vào kiến ​​trúc nhưng bạn đang sử dụng máy/trình biên dịch nào? – hhafez

+0

Trình biên dịch của Microsoft. – ChrisW

+0

Nó được đảm bảo trong ví dụ này. – fabspro

7

Trong trường hợp bạn mô tả, câu trả lời là "có thể là có". Tuy nhiên, nếu lớp có bất kỳ chức năng ảo nào (bao gồm cả destructor ảo, có thể được thừa hưởng từ một lớp cơ sở), hoặc sử dụng nhiều thừa kế thì bố cục lớp có thể khác nhau.

2

Để thêm vào những gì người khác đã nói (ví dụ: trình biên dịch cụ thể, có khả năng sẽ làm việc miễn là bạn không có chức năng ảo): kiểm tra

tôi rất muốn đề nghị một khẳng định tĩnh (thời gian biên dịch) sizeof (Example_class) == sizeof (example_struct) nếu bạn đang làm điều này. Xem BOOST_STATIC_ASSERT, hoặc xây dựng trình biên dịch cụ thể hoặc tùy chỉnh tương đương. Đây là hàng phòng thủ tốt đầu tiên nếu ai đó (hoặc thứ gì đó, chẳng hạn như thay đổi trình biên dịch) sửa đổi lớp để làm mất hiệu lực đối sánh. Nếu bạn muốn kiểm tra thêm, bạn cũng có thể kiểm tra thời gian chạy để bù đắp cho các thành viên là như nhau, mà (cùng với khẳng định kích thước tĩnh) sẽ đảm bảo tính chính xác.

0

Các lớp & cấu trúc trong C++ là tương đương, ngoại trừ tất cả các thành viên của một cấu trúc được công khai theo mặc định (thành viên lớp là riêng tư theo mặc định). Điều này đảm bảo rằng việc biên dịch mã C cũ trong trình biên dịch C++ sẽ hoạt động như mong đợi.

Có gì ngăn cản bạn từ việc sử dụng tất cả các fancy C++ tính năng trong một cấu trúc:

struct ReallyAClass 
{ 
    ReallyAClass(); 
    virtual !ReallAClass(); 

    /// etc etc etc 
}; 
+0

Tôi nghĩ rằng sự tương đương này chỉ có nghĩa là bạn có thể biên dịch mã C như mã C++ – user44511

+0

Chúng tương đương với một cách nào đó, nhưng tôi nghi ngờ (mặc dù tôi không biết) cho dù tiêu chuẩn nói rằng bố trí trong bộ nhớ của chúng giống hệt nhau ; Ngoài ra, có một 'virtual'method (như trong ví dụ sai sót của bạn) ** sẽ ** có khả năng thay đổi cách bố trí (bằng cách thêm một vptr cho mỗi thể hiện). – ChrisW

+1

Tất cả các trình biên dịch thông thường đặt con trỏ vtable ở đầu của đối tượng, do đó, có một phương thức ảo ** sẽ ** thay đổi bố cục bộ nhớ của lớp. C++ đảm bảo hành vi giống hệt nhau chỉ cho các loại POD ("Dữ liệu cũ"): một cấu trúc hoặc lớp phải tuân theo một số hạn chế để phân loại là POD. –

0

Tại sao không chỉ định rõ ràng các thành viên của lớp cho cấu trúc khi bạn muốn chuyển dữ liệu đến C? Bằng cách đó bạn biết mã của bạn sẽ hoạt động ở mọi nơi.

-2

Bạn có thể chỉ lấy được lớp từ cấu trúc, công khai hoặc riêng tư. Sau đó, nó sẽ giải quyết chính xác trong mã C++.

0

Trong những ngày đầu của trình biên dịch C++ có các ví dụ khi trình biên dịch thay đổi đầu tiên từ khóa cấu trúc với lớp và sau đó biên dịch. Vì vậy, nhiều về tương đồng.

Sự khác biệt đến từ thừa kế lớp và đặc biệt là các hàm ảo. Nếu lớp chứa các hàm ảo, thì nó phải có một con trỏ để nhập bộ mô tả vào đầu bố cục của nó. Ngoài ra, nếu lớp B kế thừa từ lớp A, thì bố cục của lớp A đến trước, tiếp theo là bố cục của lớp B.

Vì vậy, câu trả lời chính xác cho câu hỏi của bạn về việc truyền một cá thể lớp tới một cá thể cấu trúc là: phụ thuộc vào nội dung lớp. Đối với một lớp cụ thể có các phương thức (hàm tạo và hàm hủy không ảo), bố cục có thể sẽ giống nhau. Nếu destructor được khai báo ảo, bố cục chắc chắn sẽ trở nên khác nhau giữa cấu trúc và lớp.

Dưới đây là một bài báo trong đó cho thấy rằng không có nhiều cần phải làm gì để bước từ cấu trúc C đến C++ lớp: Lesson 1 - From Structure to Class

Và đây là bài viết sẽ giải thích cách bảng chức năng ảo được giới thiệu đến các lớp học có ảo chức năng: Lesson 4 - Polymorphism

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