2010-05-29 27 views
7

Bản sao có thể xảy ra:
C++: ptr->hello(); /* VERSUS */ (*ptr).hello();
Why does C have a distinction between -> and . ?Lý do cơ bản cho sự khác biệt giữa -> và. trong c/C++?

Tôi biết sự khác biệt giữa các nhà điều hành viên và các thành viên bằng cách điều hành con trỏ (->) (.).

Tại sao các nhà thiết kế C tạo một toán tử khác cho quyền truy cập này? Tại sao trình biên dịch không thể tự tìm ra nó?

Nếu bạn luôn sử dụng a. không có trường hợp nào tồn tại, nơi nó là mơ hồ cho dù bạn có nghĩa là một thành viên hoặc một thành viên bằng con trỏ?

chỉnh sửa: Tôi không tìm cú pháp "(* a) .b". Tôi hỏi tại sao các nhà thiết kế không cho phép bạn sử dụng "a.b" thay vì "a-> b"?

+0

Ký hiệu ban đầu xuất phát từ C. –

+0

điểm tốt: Tôi đã thay đổi câu hỏi để sử dụng C thay vì C++. –

+0

có thể trùng lặp của [C++: ptr-> hello();/* VERSUS */(* ptr) .hello();] (http://stackoverflow.com/questions/447543/c-ptr-hello-versus-ptr-hello) và [sự khác biệt giữa (.) dot toán tử và (->) mũi tên trong c + +] (http://stackoverflow.com/questions/1238613/what-is-the-difference-between-dot-operator-and-arrow-in-c) –

Trả lời

0

Khi bạn có một ngôn ngữ có nghĩa là "bộ lắp ráp di động", bạn không cố giấu chi tiết triển khai từ người dùng. Tất nhiên trình biên dịch có thể tìm ra rằng trong biểu thức a.b, a được đề cập là một con trỏ. Bạn có thể? Đáng tin cậy? Tất cả thời gian? Trong lông, mã phức tạp?Và bạn có thể không hình dung ra một tình huống mà không thể nhanh chóng lưu ý rằng a là một con trỏ có thể là một vấn đề?

Ngừng suy nghĩ về mặt "khó viết" và bắt đầu suy nghĩ về "dễ đọc". (Vâng, tôi biết. Điều này đi ngược lại với toàn bộ các nhà lập trình C thần thoại!) Bạn sẽ đọc mã một vài đơn đặt hàng về cường độ thường xuyên hơn bạn sẽ viết nó.

6

Bạn có thực sự muốn trình biên dịch "tự tìm ra nó không?" Nếu nó đã làm, sau đó những điều sau đây sẽ đánh giá để điều tương tự (giả sử p là một con trỏ đến một cấu trúc với một thành viên x):

(*p).x; 
p.x 

Nếu dereferencing của con trỏ là tiềm ẩn ở đó, nó phải được ngầm ở khắp mọi nơi? Hãy xem xét:

int* p; 
int i = p; // should dereferencing be implicit here as well? 

Tôi nghĩ rằng điều này sẽ khó hiểu hơn nhiều so với hai toán tử riêng biệt.

Cũng có thể hữu ích khi có hai toán tử để giúp theo dõi số lượng lớp không giới hạn mà bạn có. Cấp, các nhà điều hành -> là không cần thiết cho việc này, vì p->x tương đương với (*p).x, nhưng nó làm cho mã một chút rõ ràng hơn và dễ đọc hơn.

+0

bạn cũng sẽ phải xem xét điều gì sẽ xảy ra khi các mức bổ sung của indirection có liên quan: bạn có muốn cho phép trình biên dịch trỏ đến các tham số 'struct' có chiều sâu tùy ý khi sử dụng' .' hay hạn chế nó đến nhiều nhất mức độ của indirection? không phải là giải pháp cảm thấy 'đúng' với tôi ... – Christoph

+0

Vâng, vì điều này (chỉ '.' cho' -> 'và' :: ') là cách nó được thực hiện bằng một số ngôn ngữ, có thể. Và dường như mọi người đến với C hoặc C++ từ những ngôn ngữ đó thấy khó hiểu khi phải phân biệt. – sbi

+0

Xem thêm [câu trả lời này] (http://stackoverflow.com/questions/2843916/c-help-about-class-and-error-c3861/2843960#2843960). – sbi

-1

(*a).b cũng giống như a->b

2

Có sự mơ hồ xuất phát từ việc có thể ghi đè lên cả hai nhà khai thác. Ví dụ tốt nhất có thể là shared pointers. Một con trỏ chia sẻ có thể được sử dụng với. và -> các toán tử và cả hai đều có ý nghĩa khác nhau.

Với -> bạn truy cập đối tượng được trỏ đến và bằng. bạn truy cập vào các thành viên của con trỏ được chia sẻ.

Ví dụ:

class MyObject { 
public: 
    void myFunction() {} 
}; 
boost::shared_ptr<MyObject> ptr; 
ptr.use_count(); // calls use_count, which is a member of boost::shared_ptr. 
ptr->myFunction(); // calls MyObject::myFunction, as the operator-> is overriden 
-1

Cả fo->bar(*fo).bar làm điều tương tự!

Ngôn ngữ chỉ đơn giản cung cấp toán tử truy cập gián tiếp, cụ thể là mũi tên (->) và coi đó là một biểu tượng duy nhất.

+0

Tại sao điều này lại được bình chọn? Nó không trả lời câu hỏi. –

+0

@Tốt Trên thực tế, bạn đã chỉnh sửa câu hỏi của mình! – Secko

-1

Toán tử -> chỉ là cách dễ dàng hơn để tham chiếu phương thức hoặc thành viên của đối tượng bằng con trỏ của nó, thay vì sử dụng một cái gì đó như (* p) .member hoặc (* p) .method.

Ví dụ:

MyClass * MyObj;

MyObj-> method(); là tốt hơn để đọc và hiểu hơn (* MyObj) .method();

0

C++ cho phép bạn vượt qua toán tử ->. Khi bạn có một lớp con trỏ thông minh như std::auto_ptr, biến tương tự có thể hỗ trợ cả .->, trên đó bạn sử dụng . để truy cập các thành viên của auto_ptr-> để truy cập các thành viên của con trỏ chứa nó.

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