Mã của bạn trông rất tuyệt như thể bạn đã quen với một ngôn ngữ khác - trong C++ sử dụng this->x
(đối với một ví dụ) là tương đối bất thường. Khi tất cả các mã được viết tốt, do đó, sử dụng một accessor hoặc mutator.
Mặc dù tôi khá bất thường trong khía cạnh đặc biệt này, tôi sẽ lưu lại (nói một lần nữa) khi nói rằng mã máy khách để sử dụng trình truy cập hoặc trình biến đổi trực tiếp là một ý tưởng tồi. Nếu bạn thành thật có một tình huống mà nó có ý nghĩa đối với mã máy khách để thao tác một giá trị trong đối tượng của bạn, thì mã máy khách nên sử dụng phép gán thông thường để đọc và/hoặc ghi giá trị đó.
Khi/nếu bạn cần kiểm soát giá trị nào được chỉ định, quá tải toán tử cho phép bạn thực hiện điều khiển đó mà không buộc cú pháp get/set xấu xí trên mã máy khách. Cụ thể, những gì bạn muốn là một lớp proxy (hoặc lớp mẫu). Chỉ với một ví dụ, một trong những tình huống phổ biến nhất mà mọi người muốn có được/thiết lập chức năng là một cái gì đó giống như một số đó là nghĩa vụ phải được giới hạn trong một số phạm vi cụ thể. Các setXXX
kiểm tra giá trị mới cho được trong phạm vi, và getXXX
trả về giá trị.
Nếu bạn muốn điều đó, một (khá) mẫu đơn giản có thể thực hiện công việc nhiều sạch hơn:
template <class T, class less=std::less<T> >
class bounded {
const T lower_, upper_;
T val_;
bool check(T const &value) {
return less()(value, lower_) || less()(upper_, value);
}
void assign(T const &value) {
if (check(value))
throw std::domain_error("Out of Range");
val_ = value;
}
public:
bounded(T const &lower, T const &upper)
: lower_(lower), upper_(upper) {}
bounded(bounded const &init)
: lower_(init.lower), upper_(init.upper)
{
assign(init);
}
bounded &operator=(T const &v) { assign(v); return *this; }
operator T() const { return val_; }
friend std::istream &operator>>(std::istream &is, bounded &b) {
T temp;
is >> temp;
if (b.check(temp))
is.setstate(std::ios::failbit);
else
b.val_ = temp;
return is;
}
};
này cũng làm cho các mã gần gũi hơn với tự chủ tài liệu - ví dụ, khi bạn khai báo một đối tượng như: bounded<int>(1, 1024);
, ngay lập tức rõ ràng rằng mục đích là một số nguyên trong phạm vi từ 1 đến 1024. Phần duy nhất ai đó có thể tìm mở cho câu hỏi là liệu 1 và/hoặc 1024 có được bao gồm trong phạm vi không.Điều này khác biệt đáng kể so với việc xác định một int trong lớp, và mong đợi tất cả mọi người nhìn vào lớp để nhận ra rằng họ phải sử dụng setXXX để thực thi một số giới hạn trên các giá trị có thể giao.
Khi bạn nhúng một trong các thứ này vào một lớp, bạn đặt biến đó thành biến công khai và phạm vi vẫn được thực thi. Trong mã máy khách, không có đối số thực trên cú pháp - bạn chỉ gán cho một biến công khai, giống như bất kỳ biến nào khác - với các chi tiết nhỏ cố gán một giá trị nằm ngoài phạm vi sẽ ném một ngoại lệ. Về mặt lý thuyết, lớp có lẽ nên lấy một tham số mẫu chính sách để xác định chính xác những gì nó làm trong trường hợp đó, nhưng tôi chưa bao giờ có một lý do thực sự để làm phiền với điều đó.
bạn có thể muốn chỉnh sửa ví dụ của bạn để phản ánh chỉnh sửa của bạn. Ngay bây giờ bạn đang quay trở lại một con trỏ không const. –
nhưng sau đó bản thân tôi sẽ không thể xóa bộ nhớ? Tôi cần phải biết làm thế nào để sở hữu một cách chính xác các biến và để cho những người khác gọi các getters mà không sửa đổi biến số dưới ... – Jonathan
getters và setters là rất Java/C# style (không phải C++). Chúng là kết quả của những ngôn ngữ này dựa vào sự phản ánh và các khuôn khổ để xây dựng đối tượng. Getters và Setter phá hủy bản chất OO của một ngôn ngữ và cho phép bạn can thiệp vào cấu trúc bên trong của một đối tượng. Đây là apon cau mày trong C++ là nó phổ biến hơn để có đối tượng được tạo thành hoàn chỉnh sau khi hàm tạo hoàn tất. –