Макро ошибки с функцией-членом - PullRequest
2 голосов
/ 26 ноября 2010

Мне весело с макросами (не)

#include <iostream>

using namespace std;

#define DEF_ATTRIBUTE(type, name) type name;\
    typedef void (*type_name_t)(CLASS_NAME*);\
    type_name_t ptr_type_name;\
    void type_name(){( ptr_type_name = &CLASS_NAME::type_name);}\

class Test
{
    public:
        #define CLASS_NAME Test
        DEF_ATTRIBUTE(int, i_Test);

        void Print()
        {
            cout << "Test::Print()" << endl;
        }
};

int main()
{
    Test t;
    t.Print();
}

, который расширяется до:

class Test
{
    public:

        int i_Test; typedef void (*type_name_t)(Test*); type_name_t ptr_type_name; void type_name(){( ptr_type_name = &Test::type_name);};

        void Print()
        {
            cout << "Test::Print()" << endl;
        }
};

и выдает ошибку компилятора:

main.cpp: в функции-члене void Test :: type_name ():
main.cpp: 16: ошибка: невозможно преобразовать void (Test :: ) () в void () (Test *)в присваивании

Насколько я понимаю, указатели функций эквивалентны.Что я делаю не так?

Ответы [ 3 ]

4 голосов
/ 26 ноября 2010

Типы указателей не эквивалентны: type_name_t - это указатель на функцию (указатель на свободную функцию), тогда как &Test::type_name - это указатель на функцию-член.Это то, что говорит вам компилятор.

Причина, по которой вы не можете преобразовать указатель на функцию-член в простой указатель на функцию, заключается в том, что (нестатическая) функция-член имеет скрытый параметр this.Вы не можете вызывать функцию-член с помощью простого указателя на функцию, поскольку невозможно передать параметр this.Вы пытаетесь объяснить это, задав свой параметр type_name_t a CLASS_NAME* - концептуально это правильно, но C ++ не работает таким образом.

Вместо того, что вам нужно сделатьдолжен указывать type_name_t как указатель на функцию-член:

typedef void (CLASS_NAME::*type_name_t)();

(не проверено. Надеюсь, синтаксис правильный; я не использую указатели на функции-члены ежедневно.)

2 голосов
/ 26 ноября 2010

Указатели функций не эквивалентны.

void (*type_name_t)(Test*)

не совпадает с

&Test::type_name

Указатель вашей функции имеет тип: указатель на функцию, которая принимает один аргумент, указатель Test и не возвращает значения.

Требуется указатель на функцию-член, в частности указатель на функцию-член, которая не принимает аргументов и не возвращает значения:

void (Test::*type_name_t) (); // note the empty parameter list!
1 голос
/ 26 ноября 2010

Типы разные.

&Test::type_name - указатель на функцию-член класса Test, тогда как type_name_t не может содержать адрес любой функции-члена класса Test.Это просто указатель на свободную функцию (не на функцию-член).

Попробуйте это:

#define CLASS_NAME Test
#define DEF_ATTRIBUTE(type, name) type name;\
    typedef void (CLASS_NAME::*type_name_t)();\
    type_name_t ptr_type_name;\
    void type_name(){( ptr_type_name = &CLASS_NAME::type_name);}\
...