Có một vài phần cho phép tất cả các tổ hợp toán tử này hoạt động theo cùng một cách.
Lý do cơ bản tại sao tất cả các công việc này là một hàm (như foo
) hoàn toàn có thể chuyển đổi thành một con trỏ đến hàm. Đây là lý do tại sao void (*p1_foo)() = foo;
hoạt động: foo
được chuyển đổi hoàn toàn thành một con trỏ thành chính nó và con trỏ đó được gán cho p1_foo
.
Unary &
, khi được áp dụng cho một hàm, tạo ra một con trỏ tới hàm, giống như nó mang lại địa chỉ của một đối tượng khi nó được áp dụng cho một đối tượng. Đối với các con trỏ tới các hàm thông thường, nó luôn luôn dư thừa do chuyển đổi hàm-con-hàm-hàm ẩn. Trong mọi trường hợp, đây là lý do tại sao void (*p3_foo)() = &foo;
làm việc.
Unary *
, khi được áp dụng cho một con trỏ hàm, tạo ra hàm trỏ, giống như nó mang lại đối tượng nhọn khi nó được áp dụng cho một con trỏ bình thường cho một đối tượng.
Những quy tắc này có thể được kết hợp. Xem xét ví dụ thứ hai của bạn đến cuối cùng , **foo
:
- Đầu tiên,
foo
được chuyển đổi hoàn toàn thành một con trỏ thành chính nó và đầu tiên *
được áp dụng cho con trỏ hàm đó, mang lại chức năng foo
một lần nữa.
- Sau đó, kết quả lại được chuyển đổi hoàn toàn thành một con trỏ thành chính nó và lần thứ hai
*
được áp dụng, một lần nữa mang lại hàm foo
.
- Sau đó, nó được chuyển đổi hoàn toàn thành một con trỏ hàm một lần nữa và được gán cho biến.
Bạn có thể thêm bao nhiêu *
s tùy thích, kết quả luôn giống nhau. Càng nhiều *
, càng tốt.
Chúng tôi cũng có thể xem xét ví dụ thứ năm của bạn , &*foo
:
- Đầu tiên,
foo
được chuyển đổi hoàn toàn thành một con trỏ đến chính nó; unary *
được áp dụng, năng suất foo
một lần nữa.
- Sau đó,
&
được áp dụng cho foo
, mang lại một con trỏ tới foo
, được gán cho biến.
Tuy nhiên, &
chỉ có thể được áp dụng cho một chức năng, không phải cho một chức năng đã được chuyển đổi thành một con trỏ hàm (tất nhiên trừ khi con trỏ hàm là một biến, trong trường hợp đó, kết quả là một con trỏ-con trỏ-con trỏ- to-a-function; ví dụ, bạn có thể thêm vào danh sách của mình void (**pp_foo)() = &p7_foo;
).
Đây là lý do tại sao &&foo
không hoạt động: &foo
không phải là một chức năng; nó là một con trỏ hàm là một giá trị. Tuy nhiên, &*&*&*&*&*&*foo
sẽ hoạt động, như vậy &******&foo
, bởi vì trong cả hai biểu thức đó, &
luôn luôn được áp dụng cho một hàm và không áp dụng cho một con trỏ hàm rvalue.
Cũng lưu ý rằng bạn không cần sử dụng unary *
để thực hiện cuộc gọi thông qua con trỏ hàm; cả hai (*p1_foo)();
và (p1_foo)();
có cùng một kết quả, một lần nữa vì chuyển đổi hàm-con-hàm-con trỏ.
&foo
lấy địa chỉ củafoo
, dẫn đến một con trỏ hàm trỏ vàofoo
, như người ta mong đợi.