2012-01-16 28 views
5

Tôi có một lớp học với một thành viên không bị thay đổi bởi các phương pháp của lớp học, vì vậy tôi đã đánh dấu nó là const. Vấn đề của tôi là tôi đã sử dụng toán tử gán mặc định giống như một hàm tạo bản sao để tránh nhiều khai báo. Nhưng trong trường hợp này toán tử gán không được tạo tự động, vì vậy tôi nhận được một số lỗi trình biên dịch: 'operator =' function is unavailable. Điều này có vẻ như không có kịch bản thực tế nào trong đó các thành viên của lớp const có thể thực sự được sử dụng (ví dụ: bạn có thấy bất kỳ thành viên const nào trong mã STL không?).Các thành viên của lớp const có hữu ích khi toán tử gán bị quá tải không?

Có cách nào để sửa lỗi này, bên cạnh việc xóa const?

EDIT: một số mã

class A 
{ 
public : 
    const int size; 
    A(const char* str) : size(strlen(str)) {} 
    A() : size(0) {} 
}; 


A create(const char* param) 
{ 
    return A(param); 
} 


void myMethod() 
{ 
    A a; 

    a = create("abcdef"); 
    // do something 

    a = create("xyz"); 
    // do something 
} 
+0

Tôi đã chỉnh sửa tiêu đề cho nội dung mà tôi nghĩ mô tả chính xác hơn ý bạn muốn hỏi và sẽ khuyến khích các câu trả lời hữu ích hơn. Nếu bạn không đồng ý, vui lòng thay đổi lại. – Crashworks

+0

@Crashworks cảm ơn! –

Trả lời

3

Dưới đây là quan niệm sai lầm của mình mà gây ra sự cố này:

[..] mà không được thay đổi bằng các phương pháp của lớp

Thành viên biến được thay đổi bằng một phương pháp lớp học của bạn, các nhà điều hành chuyển nhượng. Bao gồm cả một tổng hợp bởi trình biên dịch. Nếu bạn đánh dấu một biến thành viên là const, điều này thể hiện rằng biến này sẽ (không nên!) Thay đổi giá trị của nó trong suốt thời gian tồn tại của đối tượng. Vì vậy, rõ ràng, việc gán một giá trị mới cho đối tượng vi phạm tuyên bố này. Vì vậy, nếu bạn thực sự không muốn các thành viên thay đổi, chỉ cần không làm cho nó const.

1

Vâng, bạn có thể ghi đè lên các nhà điều hành chuyển nhượng.

Vì bạn đang sử dụng trình mặc định, trình biên dịch sẽ cố gắng sao chép các thành viên const. Đó là bất hợp pháp, vì nó là const.

class A 
{ 
private: 
    const int a; 
public : 
    A() : a(0) {} 
    A& operator = (const A& other) {return *this;} 
}; 

int main() 
{ 
    A a; 
    A b; 
    a = b; //this is legal if operator = is declared 
} 
+2

Vì vậy, giá của các thành viên const là bạn có thể cung cấp một nhà điều hành chuyển nhượng, nhưng chỉ có một người bị hỏng? – UncleBens

+1

@UncleBens tại sao điều này bị hỏng? Nó không phải, nó chỉ là không sửa đổi thành viên 'const' ... mà nên có ý nghĩa, phải không? –

+1

@UncleBens: Cho rằng thành viên 'const' trên các lh có thể giống với' rhs' vì nó chỉ được đặt trong hàm tạo, không có điểm nào trong việc sao chép nó. Nếu nó được khởi tạo khác nhau trong các nhà xây dựng khác nhau, thì bạn có thể xem xét lại thiết kế của mình! – Johnsyweb

2

const thành viên lý tưởng trong nhiều, nhiều trường hợp. tất nhiên, có trường hợp hiển nhiên mà một giá trị không nên hoặc không được thay đổi, nhưng nó cũng là một hạn chế quan trọng cho tối ưu hóa và đồng thời - không phải mọi loại đều cần hoặc phải có toán tử gán.

nếu thành viên cần hành vi của bài tập, thì biến đó không được là const.

khi giá trị/thành viên không phải đột biến hoặc bị biến đổi bởi this, nó rõ ràng hơn để cung cấp một giao diện riêng cho các thành viên biến (hoặc thậm chí là một subtype-> thành phần trong các trường hợp phức tạp hơn):

class t_text { 
public: 
// ... 
public: 
    void setString(const std::string& p); 
private: 
    const t_text_attributes d_attributes; 
    std::string d_string; 
}; 

vì vậy, đề nghị của tôi là để che giấu các nhà điều hành chuyển nhượng, và để làm cho 'đoạn có thể thay đổi' hoặc thành viên set-thể cho rõ ràng:

text.setString("TEXT"); // << Good: What you read is what happens. 
text = otherText; // << Bad: Surprise - attributes don't actually change! 
+4

Tối ưu hóa và đồng thời là những lý do quan trọng nhất để sử dụng 'const' tôi có thể nghĩ đến. Tôi muốn nói rằng điều quan trọng hơn là giữ cho bạn không làm những điều ngu ngốc bằng cách buộc bạn phải suy nghĩ (hoặc ít nhất buộc bạn phải cảm thấy một chút tội lỗi vì phải bỏ đi chòm sao). –

+0

@ Frerich có lẽ đó là một sai lầm về phía tôi, nhưng sử dụng 'const' vì lý do rõ ràng nhất đã được giả định. Tôi sẽ cập nhật điều đó để tránh nhầm lẫn. – justin

2

Bạn không thể có thành viên const và hỗ trợ, ít nhất không phải là bài tập với ngữ nghĩa dự kiến. const là, một cách hợp lý, một lời hứa rằng thành viên sẽ không bao giờ thay đổi và chuyển nhượng là (ngầm, trong tâm trí của hầu hết mọi người) một lời hứa rằng tất cả dữ liệu thành viên sẽ nhận giá trị của các thành viên bên tay phải (thường có nghĩa là thay đổi).Có một xung đột rất rõ ràng giữa hai sự kiện này.

Tất nhiên, rất nhiều loại không được hỗ trợ phân công để bắt đầu; đối với các loại không hỗ trợ chuyển nhượng, không có sự cố khi khai báo một thành viên dữ liệu const. Tuy nhiên, về tổng thể, tôi đã tìm thấy const rất nhiều ít hữu ích hơn ở đây; const là một phần của hợp đồng và các thành viên dữ liệu là không phải thường là một phần của hợp đồng bên ngoài của lớp học. (Nhưng rất nhiều phụ thuộc — nếu thành viên dữ liệu được công khai hoặc được bảo vệ, thì thực tế rằng nó không thay đổi có thể là một phần của hợp đồng bên ngoài. hoặc.)

+1

"Bạn không thể" - tốt, bạn có thể, nhưng sau đó bạn phải xác định một nhiệm vụ tùy chỉnh. Ví dụ, một đối tượng được gán hợp lý được cấp phát bởi X có thể chứa một con trỏ const đến X, để giúp yêu cầu X để deallocate đối tượng đó. Một điều như vậy có thể giải quyết một số vấn đề được áp đặt bởi một khuôn khổ hiện có, nói. Con trỏ sẽ không đổi trong suốt vòng đời của đối tượng và không được hiển thị như một phần của trạng thái đối tượng logic. I E. nó sẽ không phải là một phần của trạng thái được gán bên ngoài. Chúc mừng & hth., –

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