Указатель функции — ошибка времени компиляции

Я новичок в указателях функций, и мне нужна ваша помощь. У меня есть метод:

int test3(int i)
{
    return i;
}

Затем другим методом (не основным) я делаю:

int (*pTest3)(int) = test3;

Из примеров, которые я прочитал, это кажется нормальным. Однако я получаю ошибку времени компиляции:

testFile.cpp:277:25: ошибка: аргумент типа «int ({anonymous}::CheckingConsumer::)(int)» не соответствует «int (*)(int)»

Я не понимаю, что не так. Любая помощь будет оценена по достоинству.

Большое спасибо.


person Soc    schedule 09.08.2012    source источник
comment
Является ли эта функция функцией-членом класса? Ошибка, кажется, указывает на то, что это... Если вы хотите сделать указатель функции-члена, это немного отличается.   -  person jcoder    schedule 09.08.2012
comment
Это правильный синтаксис, должны быть какие-то другие вещи. Какой у вас компилятор? В какой области находится этот код (т.е. здесь нельзя использовать функции класса)?   -  person Valmond    schedule 09.08.2012
comment
В этом нет ничего плохого. Посмотрите на размер вашего файла (не менее 277 строк), что, возможно, есть что-то еще, что вызывает это (CheckingConsumer?), Которое вы не указали выше.   -  person Component 10    schedule 09.08.2012
comment
Было бы полезно, если бы вы могли включить в свои вопросы полный, но минимальный пример, показывающий вашу проблему. Здесь мы должны много читать между строк, чтобы сделать вывод, что test3 действительно является членом CheckingConsumer, что усложняет ответ на вопрос, чем он должен быть.   -  person Flexo    schedule 09.08.2012
comment
@ Component10 слово «метод» в вопросе ОП и сообщение об ошибке сильно намекают на то, что происходит на самом деле.   -  person Flexo    schedule 09.08.2012
comment
Для будущих вопросов, пожалуйста, попробуйте предоставить минимальный пример, демонстрирующий проблему, поскольку ваш код действительно компилируется.   -  person TemplateRex    schedule 09.08.2012
comment
@Flexo: Точно: то, что на самом деле происходит, не имеет ничего общего с примером кода оператора.   -  person Component 10    schedule 13.08.2012


Ответы (2)


Ваша test3 является функцией-членом struct или class. В функции-члены класса передается скрытый параметр this, поэтому их нельзя использовать с простыми указателями функций. Вам нужно либо объявить функцию как static, либо переместить ее за пределы struct/class, чтобы она больше не имела скрытого параметра this, либо использовать указатель на метод класса вместо указателя на функцию:

// static class method:
class X
{
    static int test3(int i)
    {
        ...
    }
};

// Non-class method, at global scope
int test3(int i)
{
    ...
}

// Class method pointer
class X
{
    int test3(int i)
    {
        ...
    }
};

// Create the method pointer
int (X::*pTest3) = &X::test3;
X *obj;
// Call the method pointer on an object
(obj ->* pTest3)(42);
person Adam Rosenfield    schedule 09.08.2012
comment
Большое спасибо за ответ. Он работал с использованием статического ключевого слова. Однако влияет ли это на программу вообще? - person Soc; 09.08.2012
comment
@user1491620 user1491620 static заставляет его не работать с экземпляром вашего класса, что значительно меняет смысл. - person Flexo; 09.08.2012

Ваш метод test3 кажется методом экземпляра. Позже вы определяете pTest3 как указатель на функцию, а не как указатель на функцию-член.

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

Объявление указателя члена с помощью typedef:

typedef int (SomeClass::*MyMethodPtr)(int i);
MyMethodPtr ptr3 = SomeClass::test3;

Теперь, используя этот указатель:

class SomeClass *pab = &ab;
int ret_value = (pab->*ptr3)(4);

Обратите внимание, что используется экземпляр класса. Есть еще один важный момент, касающийся указателей членов. Они реализованы в виде структур, которые содержат внутри от 2 до 5 простых указателей и смещений в зависимости от компилятора и других аспектов, таких как множественное наследование, наличие виртуальных базовых классов и т.д.

person Kirill Kobelev    schedule 09.08.2012