2012-03-05 35 views
5

Tôi cần một giải thích trong c + + linux.Con trỏ là thành viên hoặc Tham chiếu là thành viên

Tôi có class C1 và một class C2 khác. C1 sẽ có tham chiếu C2.

class C1 
{ 

    C2 &obj ; 

} 

tôi đang nghĩ đến việc hai lựa chọn ở đây,

  1. Trực tiếp tổ chức các tài liệu tham khảo của C2 như C2 &obj;
  2. Tạo con trỏ của C2, như c2* obj;

nào là tốt? sự khác biệt trong nó là gì? khi chọn một trong hai?

+1

Câu hỏi tương tự http://stackoverflow.com/questions/892133/should-i-prefer-pointers-or-references-in-member-data –

Trả lời

3

Tránh sử dụng thành viên tham chiếu càng nhiều càng tốt.

Sự khác biệt tương tự như tài liệu tham khảo và gợi ý áp dụng ở đây,
Nếu bạn có một thành viên tham khảo sau đó nó phải được khởi tạo tại thời điểm tạo ra các đối tượng lớp của bạn, bạn không thể có một khởi lười biếng như trong trường hợp của con trỏ thành viên bởi vì tài liệu tham khảo không thể được NULL và không thể được reseated, trong khi một thành viên con trỏ có thể được thực hiện để trỏ đến một ví dụ C2 lazily như và khi cần thiết. Ngoài ra, lưu ý rằng cũng có các tác dụng phụ khác, Khi bạn có một thành viên tham chiếu, trình biên dịch sẽ không tạo toán tử gán bản sao (=) & Bạn sẽ phải tự cung cấp cho mình. nhà điều hành = của bạn sẽ thực hiện trong trường hợp này.

Đối với hầu hết các mục đích thực tế (trừ khi bạn thực sự quan tâm đến việc sử dụng bộ nhớ cao do kích thước C2), chỉ cần giữ một phiên bản C2 là thành viên của C1 là đủ, thay vì con trỏ hoặc thành viên tham chiếu, giúp bạn tiết kiệm rất nhiều lo lắng về các vấn đề khác mà tham khảo/con trỏ thành viên mang theo mặc dù tại chi phí sử dụng bộ nhớ thêm.

Nếu bạn phải, hãy sử dụng con trỏ để đảm bảo bạn sử dụng con trỏ thông minh thay vì con trỏ thô, điều đó sẽ giúp cuộc sống của bạn dễ dàng hơn nhiều với con trỏ.

+0

Vì lý do chính xác mà bạn đã đề cập, việc sử dụng con trỏ thích hợp hơn khi sử dụng tham chiếu với tư cách thành viên. Sử dụng một tham chiếu là một giải pháp ít chung chung hơn và có thể dẫn đến hành vi đáng ngạc nhiên. Tôi sẽ đề nghị luôn tránh sử dụng tham chiếu làm thành viên. –

+0

Tôi muốn thêm rằng có những trường hợp khi giới hạn của tham chiếu khớp chính xác với những gì bạn đang cố gắng mô tả bằng mã của bạn, tức là đối tượng được liên kết với đối tượng khác trong toàn bộ thời gian tồn tại của nó (như đối tượng khóa mutex đối tượng, ví dụ). Trong những trường hợp như vậy, việc sử dụng một tham chiếu rõ ràng hơn. – Kos

0

con trỏ có hai ưu điểm chính đối với tham chiếu. con trỏ có thể là null và một con trỏ có thể được di chuyển (ví dụ toán tử ++). Việc di chuyển không giúp bạn ở đây. Nếu lớp C2 của bạn không được biết khi bạn khởi tạo C1 thì bạn nên sử dụng một con trỏ vì bạn không có cách nào để khởi tạo tham chiếu, nhưng con trỏ có thể được khởi tạo thành null.

Giống như Als đã nói, tôi cũng khuyên bạn nên sử dụng con trỏ khi cá thể C2 có thể thay đổi. Bạn có thể sử dụng tài liệu tham khảo trong trường hợp này nhưng tôi nghĩ rằng con trỏ là một giải pháp 'sạch hơn'.

+3

Nó không phải là một lợi thế mà con trỏ không cần phải được khởi tạo. – dangerousdave

0

Không tốt. Nếu bạn có bất kỳ biến số tham chiếu hoặc tham chiếu nào trỏ vào thứ gì đó được phân bổ bên ngoài lớp học của bạn, có nhiều khả năng là thiết kế chương trình là thiếu sót bằng cách nào đó.

Một trường hợp tôi có thể tìm ra vị trí hợp lý của nó, là khi bạn có một số chức năng thu gom rác đặc biệt, bên ngoài.(Ví dụ: phân bổ tự động của C++ Builder/deallocation các thành phần VCL trên heap.)

Trường hợp khác là hợp lệ, khi bạn mô phỏng cấu trúc C với lớp C++ hoặc khi viết một lớp riêng bên trong một lớp khác.

Nhưng sau đó rất có thể, cần phải chỉ ra thứ gì đó bên ngoài lớp học đến từ thiết kế chương trình thiếu sót. Tôi sẽ suy nghĩ hai lần lý do tại sao mã của tôi cần phải làm điều này, và ít nhất là cố gắng thêm độ chính xác nhiều nhất có thể vào con trỏ, tức là const *c2 const obj;

Nếu bạn có con trỏ thành viên đặc biệt như thế này, bạn cũng phải có thể tự viết một hàm tạo bản sao, toán tử gán và hàm hủy cho lớp của bạn.

Chỉnh sửa: Lý do tại sao thực tiễn không tốt này là khái niệm gọi là private encapsulation, là một trong những nền tảng của khái niệm thiết kế chương trình có tên object-oriented design.

+0

"sự cần thiết phải chỉ ra một cái gì đó bên ngoài lớp học đến từ thiết kế chương trình thiếu sót". Tôi không đồng ý, mạnh mẽ. –

+1

Bạn có thực sự muốn nói rằng bất kỳ chương trình nào sử dụng biểu đồ được thiết kế kém? Điều đó sử dụng con trỏ để điều hướng được thiết kế kém? Tôi muốn tranh luận gần như ngược lại: nếu bạn phân bổ một cái gì đó trong lớp, nó thường thích hợp hơn để làm cho đối tượng chính nó là một thành viên. Con trỏ được dành riêng cho những thứ được phân bổ bên ngoài lớp học. –

+0

@JamesKanze "Đồ thị" là gì? Điều đó có thể có nghĩa là bất cứ điều gì, mặc dù tôi giả sử bạn có nghĩa là ADT điển hình được gọi là "đồ thị". Đối với ví dụ đó, tất cả các nút (đỉnh) của biểu đồ phải được phân bổ bên trong lớp biểu đồ. Lớp nút có thể trưng ra các con trỏ tới lớp biểu đồ, nếu được khai báo là một lớp con riêng của biểu đồ. Người dùng không cần quan tâm đến con trỏ thô, họ nên điều hướng biểu đồ thông qua các hàm thành viên công khai. – Lundin

0

Bạn sẽ sử dụng cái nào, phụ thuộc vào những gì bạn cần chính xác.

Ví dụ: bạn có thể sử dụng biến thành viên tham chiếu nếu bạn cần một số loại tiêm phụ thuộc. Thậm chí sau đó, bạn có thể sử dụng con trỏ. Tuy nhiên, hãy nhớ rằng các lớp học với các thành viên tham khảo nói chung là không thể sao chép được.

Trong hầu hết các trường hợp, bạn nên sử dụng con trỏ hoặc biến thành viên giá trị.

+2

Tham khảo làm cho đối tượng không thể gán, nhưng nó vẫn có thể được sao chép. (Nhưng tôi đồng ý với điểm cơ bản của bạn: hầu hết thời gian, thích con trỏ tham chiếu trong các loại lớp. Trừ khi loại đã không thể sao chép được.) –

+0

@JamesKanze Có. Lời nói thân thiện. Ý tưởng của tôi về không thể sao chép là lớp kế thừa từ boost :: noncopyable. Trong trường hợp đó, nó cũng không thể chuyển nhượng được. Nhưng bạn có ý tôi muốn nói –

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