2008-09-08 64 views
8

Được tuyên bố như sau:Toán tử const có ý nghĩa gì khi được sử dụng với phương thức trong C++?

class A { 
public: 
    void Foo() const; 
}; 

Điều đó có nghĩa là gì?

Google lần lượt lên này:

chức năng thành viên cần được khai báo với từ khóa const sau họ nếu họ có thể hoạt động trên một const đối tượng (this). Nếu hàm không được khai báo const, trong không thể được áp dụng cho một đối tượng const, và trình biên dịch sẽ đưa ra một thông báo lỗi.

Nhưng tôi thấy có phần khó hiểu; bất cứ ai có thể đưa nó vào điều kiện tốt hơn?

Cảm ơn.

Trả lời

12

Xem xét biến thể của lớp học A.

class A { 
public: 
    void Foo() const; 
    void Moo(); 

private: 
    int m_nState; // Could add mutable keyword if desired 
    int GetState() const { return m_nState; } 
    void SetState(int val) { m_nState = val; } 
}; 

const A *A1 = new A(); 
A *A2 = new A(); 

A1->Foo(); // OK 
A2->Foo(); // OK 

A1->Moo(); // Error - Not allowed to call non-const function on const object instance 
A2->Moo(); // OK 

Từ khóa const trên khai báo hàm chỉ để trình biên dịch rằng chức năng là hợp đồng có nghĩa vụ không thay đổi tình trạng A. Do đó, bạn không thể gọi các chức năng không phải là const trong phạm vi A::Foo cũng như không thay đổi giá trị của các biến thành viên.

Để minh họa, Foo() không thể viện dẫn A::SetState vì nó được khai báo không const, A::GetState tuy nhiên là ok bởi vì nó được khai báo rõ ràng const. Thành viên m_nState không được thay đổi trừ khi được khai báo với từ khóa mutable.

Một ví dụ về cách sử dụng này là const là dành cho các hàm 'getter' để lấy giá trị của các biến thành viên.

@ 1800 Thông tin: Tôi quên mất khả năng thay đổi!

Từ khóa mutable chỉ thị trình biên dịch chấp nhận sửa đổi đối với biến thành viên mà nếu không sẽ gây ra lỗi trình biên dịch. Nó được sử dụng khi hàm cần sửa đổi trạng thái nhưng đối tượng được xem là phù hợp lôgic (hằng số) bất kể sửa đổi.

+0

Câu trả lời hay - thực sự rõ ràng và ngắn gọn. Có +1 của tôi –

1

rằng sẽ gây phương pháp để không thể thay đổi bất kỳ biến thành viên của đối tượng

3

Chức năng với const vòng loại không được phép sửa đổi bất kỳ biến thành viên. Ví dụ:

class A 
{ 
    int x; 
    mutable int y; 

    void f() const 
    { 
     x = 1; // error 
     y = 1; // ok because y is mutable 
    } 
}; 
2

C đối tượng ++ có thể được tuyên bố là const:

const A obj = new A(); 

Khi một đối tượng là const, các hàm thành viên duy nhất có thể được gọi trên đối tượng được các chức năng tuyên bố là const. Tạo một đối tượng const có thể được hiểu là làm cho đối tượng chỉ đọc. Không thể thay đổi đối tượng const, tức là không thể thay đổi thành viên dữ liệu của đối tượng. Khai báo hàm const của thành viên có nghĩa là hàm không được phép thực hiện bất kỳ thay đổi nào đối với các thành viên dữ liệu của đối tượng.

+0

Err ... const A * obj = new A(); ... Bạn quên "ngôi sao" ... :-) – paercebal

5

Đây không phải là câu trả lời, chỉ là nhận xét bên. Đó là cao được khuyến cáo để khai báo biến và hằng số const càng nhiều càng tốt.

  1. Điều này truyền đạt ý định của bạn cho người dùng lớp học của bạn (thậm chí/đặc biệt là bản thân bạn).
  2. Trình biên dịch sẽ giữ cho bạn trung thực với những ý định đó. - tức là, nó giống như tài liệu kiểm tra trình biên dịch.
  3. Theo định nghĩa, điều này ngăn cản các thay đổi trạng thái mà bạn không mong đợi và có thể, cho phép bạn đưa ra các giả định hợp lý trong khi sử dụng phương pháp của mình.
  4. const có cách thú vị để truyền bá thông qua mã của bạn. Do đó, bạn nên bắt đầu sử dụng const sớm nhất và thường xuyên nhất có thể. Quyết định bắt đầu const -xác định mã của bạn vào cuối trò chơi có thể gây đau (dễ, nhưng gây phiền nhiễu).

Nếu bạn đang sử dụng ngôn ngữ tĩnh, hãy kiểm tra thời gian biên dịch, bạn nên sử dụng càng nhiều càng tốt ... đó thực sự là một loại thử nghiệm khác.

2

Hai thực hành tốt nhất gợi ý từ kinh nghiệm:

(1) Khai báo chức năng const bất cứ khi nào có thể. Lúc đầu, tôi thấy điều này chỉ là công việc phụ, nhưng sau đó tôi bắt đầu truyền các đối tượng của mình đến các hàm có chữ ký như f (const Object & o), và đột nhiên trình biên dịch bị chặn trên một dòng trong f chẳng hạn như o.GetAValue(), bởi vì tôi đã không đánh dấu GetAValue là hàm const. Điều này có thể làm bạn ngạc nhiên khi bạn phân lớp một cái gì đó và không đánh dấu phiên bản của các phương thức ảo là const - trong trường hợp đó, biên dịch có thể thất bại trên một số chức năng mà bạn chưa bao giờ nghe trước đó được viết cho lớp cơ sở.

(2) Tránh biến có thể thay đổi khi thực tế. Một bẫy hấp dẫn có thể cho phép các hoạt động đọc thay đổi trạng thái, chẳng hạn như nếu bạn đang xây dựng một đối tượng "thông minh" có hoạt động i/o lười hoặc không đồng bộ. Nếu bạn có thể quản lý điều này chỉ với một biến nhỏ (như bool), thì theo kinh nghiệm của tôi, điều này có ý nghĩa. Tuy nhiên, nếu bạn thấy mình đánh dấu mọi biến thành viên là có thể thay đổi để giữ một số hoạt động const, bạn đang đánh bại mục đích của từ khóa const. Điều có thể xảy ra là một hàm cho rằng nó không làm thay đổi lớp của bạn (vì nó chỉ gọi các phương thức const), tôi gọi một lỗi trong mã của bạn, và có thể mất rất nhiều công sức để nhận ra lỗi này nằm trong lớp của bạn, vì coder khác (đúng) giả sử dữ liệu của bạn là const bởi vì người đó chỉ gọi các phương thức const.

2

const có cách thú vị để truyền bá thông qua mã của bạn. Vì vậy, bạn nên bắt đầu sử dụng const càng sớm càng tốt càng tốt. Quyết định bắt đầu const-ifying mã của bạn vào cuối trò chơi có thể gây đau đớn (dễ, nhưng khó chịu).

Ngoài ra, bạn sẽ dễ dàng gặp sự cố nếu phương pháp nên là const không! Điều này sẽ leo qua mã là tốt, và làm cho nó tồi tệ hơn và tồi tệ hơn.

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