Указатель на функцию
в Pascal-Delphi можно:
type
FuncPtr = function (x:integer): Integer;
FuncClsPtr = function (x:integer): Integer of object;
T=class
public
function Z(x:integer):Integer;
end;
...
var
x: FuncPtr;
y: FuncClsPtr;
C: T;
...
begin
x:=C.Z; // нельзя - ошибка компилятора
y:=C.Z; // можно
end.
int (T1::*pint) = &T1::f;
cout << (t->*p5) << endl;
T1 *t = new T1;мне кажется скобки лишние.
class t1 = object
method f x : int = x
end
open Printf
let t = new t1;;
printf "%d\n" (t#f 5);;
let p = t#f;;
printf "%d\n" (p 5);;
что это за язык?
OCaml
Компилятор не ругается, просто я бы хотел узнать, как это сделать корректно.
#include <iostream>
using namespace std;
class T1 {
public:
int f(int x) {return x;}
T1;
};
T1::T1 {
int (T1::*pint) = &T1::f;
cout << (this->*p4) << endl;
}
int main {
T1 t;
cout << t.f(5) << endl;
return 0;
}
При компиляции возникает ошибка:
class A {
public:
virtual void f { }
};
int main
{
A a;
void (A::*p;
p = &a.f;
}
Почему так? Я хочу получить указатель именно на тот f который у объекта. У потомков он может быть переопределен и я хочу получить другое значение.
1.cpp: In function 'int main':
1.cpp:10: error: ISO C++ forbids taking the address of a bound member function to form a pointer to member function. Say '&A::f'
Переопределённый метод не будет иметь смысл для объектов типа A,
то есть его нельзя присваивать переменной p.
class A
{
public:
virtual void m { std::cout << "A::m\n"; }
};
class B : public A
{
public:
virtual void m { std::cout << "B::m\n"; }
};
int main
{
void (A::*p;
p = &A::m;
A a; (a.*p;
B b; (b.*p;
return(0);
}
A::m
B::m
Хм. А как это реализовано?
в указатель номер метода в VMT запихнули
Во дела.
PS
18 p = &A::m;
(gdb) next
19 A a; (a.*p;
(gdb) print p
$1 = {__pfn = 0x1, __delta = 0}
>Во дела.
Необязательно. Например, это может быть указатель на генерируемую компилятором вспомогательную функцию, вызывающую функцию с адресом vtable + x (где х - номер метода)
И чё, в рантайме проверять, какого сорта у нас указатель?Это что ты имеешь в виду? В рантайме обычный virtual dispatch стоит, а что делать, метод-то виртуальный...
Зачем в рантайме? Все типы известны статически, VMT у потомков до определенного смещения совпадает. А для не потомков операция отсечется еще при компиляции.
gcc походу проверяет в рантайме
void call(A & o, void (A::*p
{
(o.*p;
}
Нужна же развилка, указатель на виртуальную функцию или не на виртуальную.
.type _Z4callR1AMS_FvvE, @function
_Z4callR1AMS_FvvE:
.LFB1521:
pushl %ebp
.LCFI0:
movl %esp, %ebp
.LCFI1:
subl $24, %esp
.LCFI2:
movl 12(%ebp %eax
movl 16(%ebp %edx
movl %eax, -8(%ebp)
movl %edx, -4(%ebp)
movzbl -8(%ebp %eax
xorb $1, %al
andb $1, %al
testb %al, %al
je .L2
movl -8(%ebp %eax
movl %eax, -12(%ebp)
jmp .L3
.L2:
movl -4(%ebp %eax
movl 8(%ebp %edx
addl %eax, %edx
movl -8(%ebp %eax
addl (%edx %eax
decl %eax
movl (%eax %eax
movl %eax, -12(%ebp)
.L3:
movl -4(%ebp %eax
addl 8(%ebp %eax
movl %eax, (%esp)
call *-12(%ebp)
leave
ret
void call(A & o, void (A::*p
{
mov ecx, dword ptr [esp+4]
jmp dword ptr [esp+8]
А по адресу, куда делается джамп, лежит заранее сгенерённый стаб, вызывающий нужный метод
class C
{
public:
void f (int x);
};
void (*pf) (int x); // Указатель на функцию одного параметра
void (C::*pcf) (int x); // Указатель на функцию двух параметров, один из которых неявный
void g (void)
{
pf = &C::f; // Неверно
pcf = &C::f; // Верно
}
Оставить комментарий
Jackill
Как получить указатель на функцию-член класса? Другими словами, почему этот кодне компилируется, в то время как этот
работает. В первом случае компилятор ругается так: