2010-10-30 3 views

Trả lời

61

Điều đó có nghĩa là *thisconst bên trong hàm thành viên đó, tức là nó không làm thay đổi đối tượng.

Từ khóa this là biểu thức giá trị có giá trị là địa chỉ của đối tượng mà hàm được gọi. Loại this trong chức năng thành viên của một lớp X là . Nếu chức năng thành viên được khai báo là const, loại thisconst X*. [phần 9.3.2 §1]

Trong chức năng thành viên const, đối tượng mà hàm được gọi được truy cập thông qua đường dẫn truy cập const; do đó, một hàm thành viên const sẽ không sửa đổi đối tượng và các thành viên dữ liệu không tĩnh của nó. [phần 9.3.2 §2]

Điều này có nghĩa là có thể gọi hàm const thành viên trên lớp const của lớp học. Không thể gọi hàm thành viên không phải là const trên [1] đối tượng const vì có thể có khả năng cố sửa đổi nó.

[1] Lưu ý: tạm thời không phải là một đối tượng const trừ khi nó là của const loại.

+0

ah ok thx! và làm thế nào để tôi nhận được bên trong một hàm const như một con trỏ đến một biến thành viên? nếu tôi cố gắng 'int * ptr = & m_value' Tôi nhận được một' C2440 const int * không thể được chuyển đổi thành int * ' – Mat

+0

và điều này giúp trình biên dịch để tối ưu hóa mã lắp ráp hoặc những gì chính xác là lợi ích? – Mat

+2

@Mat: khai báo biến của bạn dưới dạng const: 'const int * ptr = & m_value' –

10

Tối ưu hóa trình biên dịch là có thể, nhưng lợi ích chính là thực thi hợp đồng được biểu thị trong khai báo hàm - nếu bạn xác định hàm thành viên là const, trình biên dịch ngăn không cho sửa đổi đối tượng bên trong hàm đó.

Bạn có thể miễn các trường riêng lẻ trong lớp khỏi hạn chế này bằng cách sử dụng mutable trong tuyên bố của họ. Điều này rất hữu ích ví dụ khi bạn có một lớp đóng gói lock_guard của riêng nó, mà phải thay đổi giá trị của nó để thực thi an toàn luồng ngay cả trong các hàm thành viên const.

25

const ở cuối chữ ký hàm có nghĩa là hàm phải giả định đối tượng mà thành viên là const. Trong điều kiện thực tế nó có nghĩa là bạn yêu cầu trình biên dịch để kiểm tra rằng chức năng thành viên không thay đổi dữ liệu đối tượng theo bất kỳ cách nào. Nó có nghĩa là yêu cầu trình biên dịch kiểm tra rằng nó không trực tiếp thay đổi bất kỳ dữ liệu thành viên nào, và nó không gọi bất kỳ hàm nào mà chính nó không đảm bảo rằng nó sẽ không thay đổi đối tượng.

Khi bạn tạo đối tượng const, bạn yêu cầu trình biên dịch đảm bảo rằng đối tượng đó không thay đổi ngoài khởi tạo của nó. Điều đó có nghĩa là trình biên dịch sẽ kiểm tra bạn không trực tiếp thay đổi dữ liệu thành viên của nó và bạn không gọi bất kỳ hàm nào không đảm bảo nó sẽ không thay đổi đối tượng.

Đây là tất cả các phần của triết lý const đúng đắn. Về bản chất nó có nghĩa là nếu mọi thứ hoạt động ngay bây giờ và chúng sẽ không thay đổi thì chúng sẽ không bao giờ phá vỡ. Nói cách khác, những thứ liên tục dễ dàng hơn để làm việc một cách đáng tin cậy. Điều này const điều ở phần cuối của chữ ký chức năng là một công cụ để bạn có thể cấm mọi thứ từ phá vỡ.Điều này lần lượt có nghĩa là bạn nên đặt const ở mọi nơi bạn có thể có thể.

+0

cảm ơn lời giải thích này. là có bất kỳ đối số chống lại bằng cách sử dụng const trong một chức năng mà không thay đổi đối tượng? Tôi cảm thấy rằng phần mềm có thể ít linh hoạt hơn nếu bạn đột nhiên quyết định ví dụ để thay đổi một số thiết kế và cần gọi hàm không const trong hàm const hiện tại và sau đó có thể là một chuỗi lớn các hàm gọi hàm này quá – Mat

+1

Không, không có đối số nào chống lại việc sử dụng 'const'. Đó là, trừ khi bạn biết ngay bây giờ, tại thời điểm thiết kế lớp học của bạn, rằng một chức năng thành viên nên được phép thay đổi đối tượng. Đó là một câu hỏi thiết kế mà bạn nên tự hỏi mình sớm, và nó sẽ dễ dàng để trả lời. Nó không phải là "để cánh cửa mở ra sau này". Thay vào đó, đó là về việc liệu hàm ** có nên thay đổi đối tượng hay không ** không nên thay đổi nó. Đó là một câu hỏi có/không, màu đen hoặc trắng, không có gì ở giữa, và nó phải dễ trả lời. Lưu ý: nó không phải là về ** ** nó có thể thay đổi đối tượng, nhưng ** nên ** nó. – wilhelmtell

+1

Điều này có nghĩa là triết lý const-correctness buộc bạn sớm phải rất ý thức về những gì từng chức năng làm. Nó buộc bạn phải quyết định và rất rõ ràng về việc raison d'être của mỗi chức năng thành viên. Đó là một điều tốt. Những gì bạn đang yêu cầu là để lại một cánh cửa mở cho việc thay đổi raison d'être của một chức năng, và đó là một điều xấu. Bạn chỉ nên thay đổi ** cách ** chức năng nhận được những gì nó có nghĩa là để làm, không ** những gì ** nó. Suy nghĩ về người dùng API của bạn (bạn cũng là chính mình). Đừng kéo tấm thảm ra khỏi chân của họ! – wilhelmtell