2009-12-27 39 views
7

tôi gặp hai giải thích về hàm thành viên constvề hàm thành viên const

class A{ 
    public: 
    ... 
    void f() const {} 
    ... 
} 
  1. nó có nghĩa là nó chỉ có thể truy cập vào các thành viên liên tục;
  2. điều đó có nghĩa là nó không sửa đổi bất kỳ thành viên nào;

Tôi nghĩ điều thứ hai là đúng. Nhưng tại sao người đầu tiên đi ra? Có điều gì cần làm rõ không?

Cảm ơn!

+1

Sách C++ của bạn nói gì? –

+6

Trang web này ** là ** cuốn C++ của tôi! –

+0

Cả hai đều chính xác. Đến một mức độ (xem bên dưới). –

Trả lời

18

Bạn có thể kiểm tra tất cả các giá trị thành viên lớp trong hàm thành viên const và trong một số trường hợp, bạn thậm chí có thể thay đổi giá trị của biến thành viên. Lời giải thích đầu tiên là không chính xác, tôi không biết nó đến từ đâu. Lời giải thích thứ hai là chính xác, nhưng với một vài ngoại lệ.

Có một số ngoại lệ đối với quy tắc này. Bạn cũng có thể thay đổi các biến có thể thay đổi trong một hàm thành viên const, ví dụ một biến thành viên đã tuyên bố như thế này:

mutable float my_rank; 

Bạn cũng có thể phá vỡ const-đúng đắn trong một lớp bằng const_cast'ing một tham chiếu đến bản thân như thế này:

Class* self = const_cast<Class*> (this); 

Mặc dù về mặt kỹ thuật được cho phép trong C++, điều này thường được coi là biểu mẫu kém vì nó ném đi tất cả các công cụ sửa đổi const của thiết kế của bạn. Đừng làm điều này trừ khi bạn thực sự có, và nếu bạn thấy mình phải làm điều này khá nhiều mà cho thấy một vấn đề với thiết kế của bạn. Các C++ FAQ bao gồm này rất tốt.

Dưới đây là hai tài liệu tham khảo trong trường hợp bạn muốn làm nhiều hơn đọc:

5

Trong một ý nghĩa đơn giản, chức năng const bạn không thể thay đổi trạng thái đối tượng.

Trong chức năng const con trỏ này cư xử như con trỏ const để dữ liệu const, nơi như trong chức năng không const nó hoạt động như con trỏ const số liệu.

void foo() const --> const ClassName * const this (so you can't alter data) 

void foo() --> ClassName * const this (so you can alter data) 

Đối với thành viên dữ liệu const, bạn có thể truy cập (đọc) từ bất kỳ chức năng thành viên nào dù có hay không.

Như James Thompson đã cho thấy bạn thậm chí có thể thay đổi trạng thái của đối tượng bằng cách loại bỏ constness nếu bạn muốn như thế này.

class Bar 
{ 
    int bar; 
    public: 
    void foo() const 
    { 
     this->bar = 0; //flashes error 

     Bar * const thisClass = const_cast<Bar * const>(this); 
     thisClass->bar = 0; 
    } 
}; 

Cũng có thể thay đổi thành viên dữ liệu có thể thay đổi trong hàm const.

1

Tôi nghĩ trường hợp 1 sau khi làm rõ một số điều có thể liên quan đến tình huống khi bạn có đối tượng const loại A. Trong trường hợp này, bạn chỉ có thể gọi hàm thành viên được khai báo là const() trong trường hợp này.Vì vậy, theo bài viết của bạn, bạn phải giả định rằng 'nó' là người gọi của các thành viên chức năng trên một đối tượng của loại const A. Có lẽ bạn nên xem lại định nghĩa bạn tìm thấy có trong tâm trí giả định này.

2

Cả hai đều chính xác.

Chức năng thành viên const không thể thay đổi trạng thái của đối tượng.

  • Điều này có nghĩa là nó có thể đọc (nhưng không sửa đổi) tất cả các biến thành viên.
  • Điều này cũng có nghĩa là nó chỉ có thể gọi các hàm thành viên const khác
    Các phương pháp khác đảm bảo không thay đổi trạng thái của đối tượng.

Phía trên James cũng đề cập đến các thành viên có thể thay đổi.
Vì vậy, tôi cũng nên đề cập đến những điều đó tại đây.

Biến thành viên có thể thay đổi là biến không phải là một phần của trạng thái của đối tượng (trình biên dịch không coi đó là một phần của trạng thái đối tượng). Bạn cũng nên đối xử với nó theo cách này. Bất kỳ biến thành viên nào chứa thông tin trạng thái về đối tượng nên NOT được đánh dấu là có thể thay đổi. Bạn chỉ nên sử dụng nó để giữ thông tin tạm thời có thể được xây dựng lại từ trạng thái đối tượng.

Ví dụ đơn giản là đối tượng ngày giờ. Trường hợp đối tượng có một phương thức chuyển đổi dữ liệu/thời gian thành định dạng chuỗi có thể đọc được. Chuỗi này có thể được lưu trong bộ nhớ cache trong đối tượng trong một thành viên có thể thay đổi để có hiệu quả (do đó bạn không cần phải liên tục tạo chuỗi). Nhưng chuỗi không phải là một phần của trạng thái đối tượng (vì nó có thể được xây dựng từ các thành viên khác).

Ngoài ra, James đề cập đến việc sử dụng độ lệch đi khi sử dụng const_cast.

Ngoại trừ trong những tình huống rất đặc biệt, nơi bạn biết đối tượng KHÔNG BAO GIỜ ĐƯỢC const làm việc này được coi là một ý tưởng tồi. Vì nó dẫn trực tiếp đến hành vi không xác định. Nếu bạn thấy mình cần phải bỏ đi chòm sao thì một cái gì đó rất sai trong thiết kế đã xảy ra trong chương trình của bạn.

Thực ra tôi chỉ có thể nghĩ về một tình huống xảy ra bình thường. Và sau đó tôi không muốn cam kết nó để mã mà không cần đầu tiên đi và làm nghiên cứu để đảm bảo rằng tôi không nhìn ngớ ngẩn.

+0

Tôi nghĩ rằng bạn đọc câu hỏi đầu tiên khác với tôi. Định nghĩa được đề xuất là "nó chỉ có thể truy cập các thành viên liên tục." Một hàm thành viên const có thể truy cập các thành viên không liên tục, miễn là nó không thay đổi trạng thái của chúng, do đó định nghĩa đó không chính xác. –

+0

@James. Hãy làm cho tuyên bố của bạn rõ ràng hơn. Một phương thức const có thể đọc bất kỳ biến thành viên nào. Nhưng chỉ có thể gọi các phương thức thành viên const. Tôi nghĩ rõ ràng rằng câu hỏi ban đầu chỉ có những chi tiết nhỏ trộn lẫn. –

+0

Không phải lo lắng, mặc dù 2 ví dụ cụ thể đã được đưa ra .. Sẽ đưa ra tất cả các ý kiến ​​và bắt đầu hỗ trợ các kênh truyền thông thể hiện quan sát tầm thường. Ai biết được, có lẽ tôi sẽ bắt đầu nhìn thấy một làn đường chuyên dụng cho mỗi chiếc xe, thay vì một con đường duy nhất. –

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