почему указатели на свободные функции всегда имеют указатель типа, тогда как указатели на функции-члены на самом деле не являются указателями? - PullRequest
0 голосов
/ 30 января 2012

Я озадачен тем, как C ++ обрабатывает указатели на функции и указатели на функции-члены, поэтому я рассеиваю свои сомнения в этом примере кода:

#include <iostream>
#include <type_traits>
#include <functional>
#include <typeinfo>
using namespace std;

struct asd{ void f(){ } };
void f(){}

template<typename T> void g(T f){
    cout<<"T of g is "<<
            (is_pointer<T>::value?"pointer":
                    (is_function<T>::value?"function":
                            (is_member_function_pointer<T>::value?"member function pointer":
                                    "something else")))<<" -------- ";

    typedef typename remove_pointer<T>::type TlessPointer;
    cout<<"T of g less a pointer is "<<
            (is_pointer<TlessPointer>::value?"pointer":
                    (is_function<TlessPointer>::value?"function":
                            (is_member_function_pointer<TlessPointer>::value?"member function pointer":
                                    "something else")))<<endl;
}

int main(){
    cout<<"free function ";
    g(f);
    cout<<endl<<"(multiple times) dereferenced free function (!!!) ";
    g(******f);
    cout<<endl<<"member function ";
    g(&asd::f);
    //this won't compile: g(*&asd::f);
}

Этот код печатает:

свободная функция T of g является указателем -------- T of g меньше указателя функция

(несколько раз) свободная функция разыменования (!!!) T of g является указателем -------- T g меньше указатель - это функция

функция-член T of g является указателем на функцию-член -------- T of g less указатель является указателем на функцию-член

Итак (простите мне один раз за открытость вопроса): почему функции и указатели на функции обрабатываются так по-разному, то есть почему первые подвергаются угрозе как истинные указатели, а вторые? Есть ли исторические причины?

Ответы [ 2 ]

6 голосов
/ 30 января 2012

Указатель на функцию-член должен работать правильно, если функция виртуальная.В этом случае он не может быть просто указателем на функцию, поскольку он должен отправлять другой функции в зависимости от динамического типа объекта, к которому он применяется.

Обычно он содержит:

  • Флаг, указывающий, является ли он виртуальным;
  • Если не виртуальный, указатель «нормальной» функции;
  • Если виртуальный, индекс функции в vtable (при условии, что виртуальная диспетчеризация реализована с помощью таблицы).
4 голосов
/ 30 января 2012

Исторически C ++ происходит от C и пытается быть совместимым в общих чертах.Что касается функций, то C немного двусмыслен в отношении различий между самими функциями и указателями на функции: имя функции преобразуется в указатель на функцию, если сразу за ней не следует токен '(' и указательфункция принимает оператор '(', точно так же, как функция. По причинам совместимости, C ++ делает то же самое.

Совместимость с C не вступает в игру для функций-членов, поэтому C ++ правильно с ними работает: функция не является указателем на функцию, и нет никакой причины для неявного преобразования между ними.

(С тех пор STL использует тот факт, что вы можете «вызвать» указатель на функцию, поэтомучто вы можете использовать функции (или, скорее, указатели на функции) как вызываемые объекты.)

...