2010-06-18 45 views
26

Tôi đang cố gắng in địa chỉ của một chức năng thành viên ảo. Nếu tôi biết đó là lớp thực hiện các chức năng tôi có thể viết:Địa chỉ in của chức năng thành viên ảo

print("address: %p", &A::func); 

Nhưng tôi muốn làm một cái gì đó như thế này:

A *b = new B(); 

printf("address: %p", &b->func); 
printf("address: %p", &b->A::func); 

Tuy nhiên điều này không biên dịch. Có thể làm một cái gì đó như thế này, có lẽ nhìn lên địa chỉ trong vtable tại thời gian chạy?

Trả lời

1

Không có ý nghĩa gì đối với tôi. Nếu bạn có một chức năng bình thường:

void f(int n) { 
} 

sau đó bạn có thể lấy địa chỉ của nó:

f 

nhưng bạn không thể lấy địa chỉ của một hàm gọi, đó là những gì bạn dường như muốn làm .

+0

@GMan Đó là những gì tôi nghĩ tôi đã nói. Nhưng dù sao, tôi không nghĩ rằng điều này là có thể. –

1

Từ những gì tôi có thể nói trong tiêu chuẩn, thời gian duy nhất bạn nhận được liên kết động là trong một chức năng ảo gọi. Và khi bạn đã gọi một hàm, bạn đang thực hiện các câu lệnh trong hàm (nghĩa là bạn không thể "dừng nửa chừng" vào cuộc gọi và nhận địa chỉ.)

Tôi nghĩ điều đó là không thể.

+0

Tôi cho rằng điều đó không thể thực hiện được, nhưng biết việc triển khai nó có thể kiểm tra bảng ảo của một đối tượng trong thời gian chạy. –

6

Con trỏ tới các hàm thành viên không phải lúc nào cũng là địa chỉ bộ nhớ đơn giản. Xem bảng trong this article hiển thị kích thước của các con trỏ hàm thành viên trên các trình biên dịch khác nhau - một số đi tới 20 byte.

Khi bài viết phác thảo một con trỏ hàm thành viên thực sự là một blob dữ liệu được xác định thực hiện để giúp giải quyết cuộc gọi thông qua con trỏ. Bạn có thể lưu trữ và gọi cho họ OK, nhưng nếu bạn muốn in chúng, bạn in gì? Tốt nhất để xử lý nó như là một chuỗi các byte và có được chiều dài của nó thông qua sizeof.

+4

Tuy nhiên, vấn đề vẫn còn: làm thế nào để bạn xác định các chức năng mà có được gọi là thông qua một cuộc gọi 'ảo' :)? –

+1

Đó không phải là một phần của câu hỏi là nó? Nhưng tôi sẽ trả lời 'bằng cách gọi nó' :) – AshleysBrain

11

Hiện tại không có cách nào tiêu chuẩn để thực hiện việc này trong C++ mặc dù thông tin phải có sẵn ở đâu đó. Nếu không, chương trình có thể gọi hàm như thế nào? Tuy nhiên, GCC cung cấp một phần mở rộng cho phép chúng ta lấy địa chỉ của một hàm ảo:

void (A::*mfp)() = &A::func; 
printf("address: %p", (void*)(b->*mfp)); 

... giả sử các hàm thành viên có nguyên mẫu void func(). Điều này có thể khá hữu ích khi bạn muốn lưu địa chỉ của một hàm ảo hoặc sử dụng nó trong mã được tạo. GCC sẽ cảnh báo bạn về cấu trúc này trừ khi bạn chỉ định -Wno-pmf-conversions. Nó không chắc rằng nó hoạt động với bất kỳ trình biên dịch nào khác.

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