typedef std::queue<int> Q;
Q
là queue
vùng chứa thích hợp.
typedef Q::container_type C;
C
là container cơ bản của Q
- mà là một deque<int>
.
C & get (Q &q) {
get
mất một queue
và trả về một deque
. Trong thực tế nó trả về deque
rằng các kết thúc queue
: bằng phương tiện thông thường, điều này là không thể.
struct hack : private Q {
hack
là loại cục bộ cho hàm. Nó kế thừa từ Q
và chỉ có một hàm thành viên tĩnh. Từ tên của nó, bạn có thể nghi ngờ nó là một hack. Bạn đúng rồi.
Không hack
là bao giờ được khởi tạo.
static C & get (Q &q) {
hack::get
có cùng chữ ký với số get
. Trong thực tế, chúng tôi ủy nhiệm tất cả công việc của get
cho phương pháp này.
return q.*&hack::c;
dòng này cần được chia nhỏ. Tôi sẽ làm điều đó trong nhiều dòng:
using mem_ptr_t = C Q::*; // aka typedef C Q::*mem_ptr_t;
mem_ptr_t c_mem_ptr = &hack::c;
C& ret = q.*c_mem_ptr;
return ret;
Dòng đầu tiên xác định loại của một con trỏ thành viên đến một lĩnh vực loại C
trong một Q
. Cả C++ 11 và C++ 03 cách đặt tên kiểu này đều xấu.
Dòng thứ hai là con trỏ thành viên đến trường c
trong Q
. Nó thực hiện điều này thông qua các lỗ hổng trong hệ thống kiểu của C++. &hack::c
là hợp lý của loại C hack::*
- một con trỏ đến một thành viên thuộc loại C
trong một loại thuộc loại hack
. Thực tế, đó là lý do tại sao chúng tôi có thể truy cập nó trong một thành viên static
của hack
. Nhưng c
được đề cập thực sự là trong Q
, do đó loại thực tế của biểu thức trong C++ là C Q::*
: một con trỏ đến biến thành viên là Q
.
Bạn không thể trực tiếp nhận con trỏ thành viên này trong phạm vi hack
- &Q::c
là bất hợp pháp, nhưng &hack::c
thì không.
Bạn có thể nghĩ đến con trỏ thành viên là 'offsets gõ' vào loại khác: &hack::c
là "bù đắp" của c
trong Q
cùng với biết nó là loại C
. Bây giờ điều này không thực sự đúng - đó là một số giá trị mờ cho trình biên dịch biết cách lấy c
từ Q
- nhưng nó giúp nghĩ về nó theo cách đó (và nó có thể được thực hiện theo cách đó trong các trường hợp đơn giản).
Sau đó, chúng tôi sử dụng con trỏ thành viên này cùng với Q&
để lấy số c
ra khỏi số Q
. Bắt một con trỏ thành viên bị ràng buộc bởi bảo vệ: sử dụng nó không phải là! Cách chúng tôi thực hiện với nhà điều hành .*
, là nhà điều hành dereference thành viên, bạn có thể chuyển các con trỏ chức năng thành viên hoặc thành viên ở bên phải và các phiên bản lớp ở bên trái.
instance .* member_ptr
là cụm từ tìm thấy thành viên "được trỏ tới" bởi member_ptr
trong số instance
. Trong mã ban đầu, mọi thứ được thực hiện trên một dòng:
instance .* &class_name::member_name
vì vậy có vẻ như có một nhà điều hành .*&
.
}
};
và sau đó chúng tôi đóng lên các phương pháp tĩnh và hack
lớp, và:
return hack::get(q);
}
gọi nó. Kỹ thuật này cho phép truy cập vào trạng thái protected
: không có nó, protected
thành viên chỉ có thể được truy cập trong các lớp con của cùng một trường hợp. Sử dụng điều này, chúng tôi có thể truy cập protected
thành viên của bất kỳ trường hợp nào mà không vi phạm bất kỳ tiêu chuẩn nào.
Đó là hai toán tử: '. *' Và '&'. – chris
Tôi nghĩ rằng mẹo có thể đã được lấy cảm hứng từ http://stackoverflow.com/a/1065606/962089 – chris
@chris Đó là một phát hiện mang tính phân biệt. Cảm ơn vì điều này! –