Error a pointer to a bound function may only be used to call the function

I've been trying to assign a function pointer (of a class) to a member function (of another class) like this: --- Game.h --- #ifndef GAME_H #define GAME_H #include "Screen.h" class Game { privat...

I’ve been trying to assign a function pointer (of a class) to a member function (of another class) like this:

--- Game.h ---
#ifndef GAME_H
#define GAME_H

#include "Screen.h"

class Game
{
private:
    void (*HandleCurrentScreen)();

public:
    void SetScreen(const Screen& newScreen);
};

#endif



--- Game.cpp ---
#include "Game.h"
#include "Screen.h"

void Game::SetScreen(const Screen& newScreen)
{
    HandleCurrentScreen = newScreen.Handle;    //Produces the error
}



--- Screen.h ---
#ifndef SCREEN_H
#define SCREEN_H

class Screen
{
public:
    void Handle();
};

#endif



--- Screen.cpp ---
#include "Screen.h"

void Screen::Handle()
{
    ...
}

I get this error:

error C3867: ‘Screen::Handle’: function call missing argument list; use ‘&Screen::Handle’ to create a pointer to member

It seems to work fine if HandleCurrentScreen points to a function that is also defined in the Game class. I’ve been looking for other people with this problem, but none seem to have it in cases like this.

A solution that might work is something like this:

Screen* p_currentScreen;

void Game::SetScreen(const Screen& newScreen)
{
    p_currentScreen = &newScreen;
}

and then instead of calling HandleCurrentScreen I can call p_currentScreen->Handle(), but this seems slightly less efficient to me.

What can I do to fix this? Should I just use a pointer to a class instead of a function pointer?

Any advice is welcome.

September 26th, 2022

TL;DR: You got all set to call a member function but forgot to call it.

void oops(std::vector<std::string>& v)
{
    set_name(v.front.c_str());
    //         ^^^^^ error: A pointer to a bound function
    //         may only be used to call the function
}

What you meant was

void oops(std::vector<std::string>& v)
{
    set_name(v.front().c_str());
    //              ^^
}

Here’s how to decode the error message:

A “bound function” is

  • An object, a dot, and a member function name, or
  • A pointer, a -> arrow, and a member function name.

In the above example, it is the v.front.

Once you write v.front, the only thing you can do next is follow up with parentheses to call the member function. If you forget the parentheses, then you get an error from the compiler that’s basically saying, “The only thing you are allowed to do is use parentheses to call the function, but you didn’t do that!”

Usually it’s because you got all set up to the call the function, and then got distracted and forgot to call it.

So call the function. That’s what you wanted to do in the first place. You just forgot to do it.

Bonus chatter: Many years ago, I was buying tickets at a ticket office (back when you bought tickets at a ticket office), and I got so distracted by the process of buying and paying for tickets that I left the counter without my tickets! Fortunately, I had gotten only a few steps away, and the tickets were waiting for me when I turned around and went back.

  • Forum
  • General C++ Programming
  • C++ Pointer to a function error

C++ Pointer to a function error

Hello, I’ve been having a problem I can’t seem to solve on ym own whole day. I’m really new to C++ so I hope you can give me a hand.

I have a class Calendar which has an attribute of priority queue, that accepts records of structure defined as:

1
2
3
4
5
6
7
typedef void (Calendar::*eventPointer)();

struct activationRecord {
	double Time;
	int Priority;
	eventPointer activationEvent;
};

And here is the problem. Whole day I’ve been trying to fill the Calendar with some test entries by calling the method

 
void Calendar::calendarPush(double Time, int Priority, eventPointer event)

This is how I call it

 
calendar.calendarPush(Time, Priority, &Calendar::calendarEmpty);

But Visual Studio keeps to warn me with this error

 
argument of type "bool (Calendar::*)()" is incompatible with parameter of type "eventPointer *"

Does anyone know what I am doing wrong?

Thank you, I’m starting to be really depressed about this as I’ve been stuck whole day, unable to solve this.

If it helps, here is a whole CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

#include <iostream>

#include "Calendar.h"

using namespace std;

int main() {


	cout << "Initializing ..." << endl;

	double Time = 0.0;
	int Priority = 0;
	Calendar calendar;

	cout << "Pushing first activation record .." << endl;

	calendar.calendarPush(Time, Priority, &Calendar::calendarEmpty);

}

----------CALENDAR.H------------

#include <iostream>
#include <queue>

using namespace std;

typedef void (Calendar::*eventPointer)();

struct activationRecord {
	double Time;
	int Priority;
	eventPointer activationEvent;
};


bool operator <(const activationRecord & a, const activationRecord & b) {
    return a.Time > b.Time;
}

class Calendar {

private:
	std::priority_queue<activationRecord> activationCalendar;

public:
	bool calendarEmpty();

	void calendarPush(double, int, eventPointer);

	activationRecord calendarTop();
	void calendarPop();

};


----------CALENDAR.CPP----------

#include "Calendar.h"

bool Calendar::calendarEmpty() {

	return activationCalendar.empty();
}

void Calendar::calendarPush(double Time, int Priority, eventPointer event) {

	activationRecord record;

	record.Time = Time;
	record.Priority = Priority;
	record.activationEvent = event;

	activationCalendar.push(record);
}

activationRecord Calendar::calendarTop() {

	return activationCalendar.top();
}

void Calendar::calendarPop() {

	activationCalendar.pop();
}

Last edited on

I have a class Calendar which has an attribute of priority queue, that accepts records of structure defined as:

typedef void (Calendar::*eventPointer)();

This is how I call it:

calendar.calendarPush(Time, Priority, &Calendar::calendarEmpty);

But Visual Studio keeps to warn me with this error

argument of type "bool (Calendar::*)()" is incompatible with parameter of type "eventPointer *"

Notice that the return type for your eventPointer typedef is void while the return type of Calendar::calendarEmpty is bool which is what the diagnostic is indicating.

Last edited on

Thank You for a reply cire,

even if I change the call from

 
calendar.calendarPush(Time, Priority, &Calendar::calendarEmpty);

for example to

 
calendar.calendarPush(Time, Priority, &Calendar::calendarPop);

even though the data types now do correspond, I’m getting an error

 
 argument of type "void (Calendar::*)()" is incompatible with parameter of type "eventPointer *"

in a Main.cpp and one more error in Calendar.cpp on line with

 
record.activationEvent = event;

saying that

 
a pointer to a bound function may only be used to call the function

I feel like I’m the dumbest person on the Earth, since I havent been able to solve this whole day, but I just ..

I think something is different with your code than what you’re posting.

 argument of type "void (Calendar::*)()" is incompatible with parameter of type "eventPointer *"

Your Calendar::push signature doesn’t take a value of type eventPointer*. It takes a value of type eventPointer.

Does this simple code compile for you?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

struct A
{
    typedef void (A::*eventType)();

    void eventFunc() {std::cout << "eventFunc()n";}

    eventType func;
};

int main()
{
    A a;
    a.func = &A::eventFunc;

    (a.*a.func)(); // invoke the pointer with object a
}

You may find http://www.parashift.com/c++-faq/pointers-to-members.html helpful.

Last edited on

Well, i just tried adding

before i define it in Calendar.h, right after the

and it works.

I don’t know why, I don’t understand why, im totally wtf .. But happy.

Topic archived. No new replies allowed.

What I want to do with the method .movement that has the error is that the player moves between the boxes. I repeat the method several times to try to fix it but don’t worry about that I can delete those.

This is the class Board which is where appears the error.

#include <iostream>
#include <string>
#include <ctime>
#include "Player2.h"
#include "Boxes2.h"

using namespace std;

class Board{

    public:

    void loop(char **board, int **positions, int y, int x);
    void draw(char **board, int **positions, int y, int x);
    void Movement(int &movement, bool playerFlag);
    void movement(int &movement, bool playerFlag);

};

Player pl;
Boxes box;
Board bd;

void Board::movement(int &movement, bool playerFlag)
{
    //true means player 1
    //false means player 2
    int diceRoll;
    int status = 0;
    if (playerFlag == true)
    {
        cout << "Player 1: Press 1 to roll the dice." << endl;
        cin >> status;
        if (status == 1)
        {
            diceRoll = 1 + rand() % 6;
            movement = diceRoll;
            cout << "Player 1 rolled a " << diceRoll << endl;
        }
    }
    if (playerFlag == false)
    {
        cout << "Player 2: Press 2 to roll the dice." << endl;
        cin >> status;
        if (status == 2)
        {
            diceRoll = 1 + rand() % 6;
            movement = diceRoll;
            cout << "Player 2 rolled a " << diceRoll << endl;
        }
    }
}

void Board::Movement(int &movement, bool playerFlag)
{
    //true means player 1
    //false means player 2
    int diceRoll;
    int status = 0;
    if (playerFlag == true)
    {
        cout << "Player 1: Press 1 to roll the dice." << endl;
        cin >> status;
        if (status == 1)
        {
            diceRoll = 1 + rand() % 6;
            movement = diceRoll;
            cout << "Player 1 rolled a " << diceRoll << endl;
        }
    }
    if (playerFlag == false)
    {
        cout << "Player 2: Press 2 to roll the dice." << endl;
        cin >> status;
        if (status == 2)
        {
            diceRoll = 1 + rand() % 6;
            movement = diceRoll;
            cout << "Player 2 rolled a " << diceRoll << endl;
        }
    }
}

void Board::loop(char **board, int **positions, int x, int y)
{
    //initalise x location of players
    player1.location = 0;
    player2.location = 0;
    //initalise y location of players
    player1.level = y - 1;
    player2.level = y - 1;
    //game flag
    bool game = true;

    while (game == true)
    {
        bd.Movement(player1.movement, true); //allow player to make move
        pl.logic(board, positions, y, x, player1.movement, player1.location, player1.level, player1.movestatus); //update location & level

        if (pl.checkWin(y, x, player1.location, player1.level) == true) //check if player won the game
        {
            cout << "Player 1 won the game." << endl;
            game = false;
        }
        else //if not 
        {
            pl.updatePlayerLevel(positions, y, x, player1.location, player1.level, player1.movestatus); //check if player has hit a snake or ladder
            board[player1.level][player1.location] = player1.symbol; //fill board with new player location
            draw(board, positions, y, x); //draw the board
        }
        if (player2.on == true)
        {
            bd.Movement(player2.movement, false);
            pl.logic(board, positions, y, x, player2.movement, player2.location, player2.level, player2.movestatus);

            if (pl.checkWin(y, x, player2.location, player2.level) == true)
            {
                cout << "Player 2 won the game." << endl;
                game = false;
            }
            else
            {
                pl.updatePlayerLevel(positions, y, x, player2.location, player2.level, player2.movestatus);
                board[player2.level][player2.location] = player2.symbol;
                draw(board, positions, y, x);
            }
        }
    }
}

void Board::draw(char **board, int **positions, int y, int x)
{
    //draw the starting and finishing point
    if (y % 2 != 0)
    {
        board[0][x - 1] = 'O';
    }
    else
    {
        board[0][0] = 'O';
    }

    board[y - 1][0] = 'O';

    //draw the level numbers
    for (int i = 0; i < y; i++)
    {
        if ((y - i) > 9)
            cout << y - i << " |";
        else
            cout << y - i << "  |";
        for (int y = 0; y < x; y++)
        {
            cout << board[i][y] << " ";
        }
        cout << endl;
    }

    if (y < 8)
    {
        //just two ladders and one snake
        box.fillLadder(board, positions, y - 1, 2, y / 2);
        box.fillLadder(board, positions, y / 2, 4, 2);
        box.fillSnake(board, positions, 0, 1, -1 * y / 2 + 1);
    }
    if (y >= 8 && y <= 12)
    {
        //just three ladders and three snakes
        box.fillLadder(board, positions, y - 1, 3, 3);
        box.fillLadder(board, positions, 4, x - 3, 2);
        box.fillLadder(board, positions, 2, x - 2, 2);

        box.fillSnake(board, positions, 0, 4, -4);
        box.fillSnake(board, positions, 4, x - 4, -4);
        box.fillSnake(board, positions, 4, 0, -3);
    }

    if (y > 12)
    {
        //just 4 ladders and 4 snakes
        box.fillLadder(board, positions, y - 1, 3, 6);
        box.fillLadder(board, positions, 6, x - 3, 5);
        box.fillLadder(board, positions, 7, x - 2, 6);
        box.fillLadder(board, positions, 9, 3, 3);
        
        box.fillSnake(board, positions, 0, 4, -7);
        box.fillSnake(board, positions, 4, x - 4, -6);
        box.fillSnake(board, positions, 7, 0, -3);
        box.fillSnake(board, positions, 5, 2, -2);
    }
}

And this is the class Player which is related to the object player

#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#pragma once


using namespace std;

class Player{

    public: 

    int movement;
    int location;
    int level;

    int movestatus = 1;

    char symbol = 1;

    bool on = false;

    void logic(char **board, int **positions, int y, int x, int movement, int &player_location, int &level, int &moveStatus);
    void movement(int &movement, bool playerFlag);
    bool checkWin(int y, int x, int player_location, int level);
    void updatePlayerLevel(int **positions, int y, int x, int player_location, int &level, int &moveStatus);
};

Player player1;
Player player2;

void Player::logic(char **board, int **positions, int y, int x, int movement, int &player_location, int &level, int &moveStatus)
{
    int remainder;
    int previous_location = player_location;
    int previous_level = level;

    if (moveStatus == 1)
    {
        player_location += movement; //if status is set to right, move right
    }
    if (moveStatus == -1)
    {
        player_location -= movement; //if status is set to left, move left
    }

    if (player_location > x - 1) //if too far from board, update the level and move accordingly
    {
        if (level != 0)
        {
            moveStatus = -1;
            remainder = player_location - (x);
            player_location = (x - 1) - remainder;
            level--;
        }
    }

    if (player_location < 0) //if too far from board, update the level and move accordingly
    {
        if (level != 0)
        {
            moveStatus = 1;
            remainder = x - 2 - player_location - (x - 1);
            player_location = remainder;
            level--;
        }
    }

    board[previous_level][previous_location] = 'N'; //fill last position of player with a dash
}

void Player::movement(int &movement, bool playerFlag)
{
    //true means player 1
    //false means player 2
    int diceRoll;
    int status = 0;
    if (playerFlag == true)
    {
        cout << "Player 1: Press 1 to roll the dice." << endl;
        cin >> status;
        if (status == 1)
        {
            diceRoll = 1 + rand() % 6;
            movement = diceRoll;
            cout << "Player 1 rolled a " << diceRoll << endl;
        }
    }
    if (playerFlag == false)
    {
        cout << "Player 2: Press 2 to roll the dice." << endl;
        cin >> status;
        if (status == 2)
        {
            diceRoll = 1 + rand() % 6;
            movement = diceRoll;
            cout << "Player 2 rolled a " << diceRoll << endl;
        }
    }
}

bool Player::checkWin(int y, int x, int player_location, int level)
{
    //if player reaches the winning location, return true.
    //winning location depends if board y-axis is even or odd
    if (player_location <= 0 && level == 0)
        return true;

    if (player_location >= x - 1 && level == 0)
        return true;

    return false;
}

void Player::updatePlayerLevel(int **positions, int y, int x, int player_location, int &level, int &moveStatus)
{
    //if a player hits a ladder and IS NOT WINNING, update level
    if (checkWin(y, x, player_location, level) == false)
    {
        if (*(*(positions + level) + player_location) > 0)
        {
            cout << "You hit a ladder" << endl;
            int length = positions[level][player_location];
            level = level - length;
            if (length % 2 != 0)
            {
                moveStatus = moveStatus * -1;
            }
        }
        //if a player hits a snake and IS NOT WINNING, update level
        if (*(*(positions + level) + player_location) < 0)
        {
            cout << "You hit a snake" << endl;
            int length = positions[level][player_location];
            level = level - length;
            if (length % 2 != 0)
            {
                moveStatus = moveStatus * -1;
            }
        }
    }
}

    msm.ru

    Нравится ресурс?

    Помоги проекту!

    >
    указатель на функцию-элемент класса…
    , или адрес функции-элемента класса. не получается.

    • Подписаться на тему
    • Сообщить другу
    • Скачать/распечатать тему



    Сообщ.
    #1

    ,
    18.07.06, 23:37

      Подскажите, пожалуйста, как разобраться с проблемкой в программе:
      Решил попробовать использовать классы С++ и наткнулся вот на какую ситуацию.
      у меня есть два класса. в одном описан элемент-функция. во втором — элемент-указатель на функцию.
      Хочется присвоить указателю адрес этой функции-элемента, а не получается. Вот если указателю
      подсунуть «просто функцию», вне класса — всё нормально.
      Для иллюстрации набросал вот такой примерчик:

      ExpandedWrap disabled

        //———————

        class class_a

        {

          public:

            char (*fptr)(char);

        };

        //———————

        class class_b

        {

          public:

            char f(char);

        };

        //——————-

        char class_b::f(char)

        {

          return ‘!’;

        }

        //——————-

        char f2(char)

        {

          return ‘~’;

        }

        //——————-

        int main()

        {

          class_a a;

          class_b b;

          a.fptr = f2;

        //  a.fptr = b.f;       // Error[Pe300]: a pointer to a bound function may only be used to call the

                                    //function

        //  a.fptr = class_b::f;// Error[Pe513]: a value of type «char (__code class_b::*)(char)» cannot be

                                    //assigned to an entity of type «char (*)(char)»

          return 0;

        }

      вот f2, функция «сама по себе», нормально присваивается. а на закомментированные строчки
      компилятор ругается. как правильно надо? Просьба гнилыми помидорами не забрасывать :).

      ЗЫ. компилятор используется IAR 3.21, но стандарты языка везде одинаковы…

      Сообщение отредактировано: trainer — 19.07.06, 12:36


      Russel



      Сообщ.
      #2

      ,
      19.07.06, 00:04

        Full Member

        ***

        Рейтинг (т): 8

        Предположение — сделать метод в классе B, который будет возвращать указатель на функцию class_b::f, и вызывать этот метод из класса class_a?


        Unreal Man



        Сообщ.
        #3

        ,
        19.07.06, 01:00

          Цитата //nikson @ 18.07.06, 23:37

          // a.fptr = b.f; // Error

          Или делай свою функцию в class_b статической, или используй тип (class_b::*)(char) в качестве указателя на функцию.


          Flex Ferrum



          Сообщ.
          #4

          ,
          19.07.06, 07:08

            Цитата //nikson @ 18.07.06, 23:37

            вот f2, функция «сама по себе», нормально присваивается. а на закомментированные строчки
            компилятор ругается. как правильно надо? Просьба гнилыми помидорами не забрасывать

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

            ExpandedWrap disabled

              //———————

              class class_a

              {

                public:

                  boost::function<char (char)> fptr;

              };

              //———————

              class class_b

              {

                public:

                  char f(char);

              };

              //…

              //…

              int main()

              {

                class_a a;

                class_b b;

                a.fptr = boost::bind(&b::f, &b, _1);

                a.fptr(‘A’);

                return 0;

              }


            Sazabis



            Сообщ.
            #5

            ,
            19.07.06, 07:11

              ExpandedWrap disabled

                class MyClass{

                    typedef long ( MyClass::* FPTR )( int );

                  public:

                    long func( int a ){ return ++a; }

                    long func( int a, char b ){ return a += b; }

                    void anyfunc( FPTR function, int a ){

                      a = (this->*function)( a );

                    }

                    void runfunc(){

                      anyfunc( &MyClass::func, 5 );

                    }

                };


              BlackEmperor



              Сообщ.
              #6

              ,
              19.07.06, 07:18

                ExpandedWrap disabled

                  //———————

                  class class_b

                  {

                    public:

                      char f(char);

                  };

                  //——————-

                  char class_b::f(char)

                  {

                    return ‘!’;

                  }

                  class class_a

                  {

                    public:

                    char (class_b::*fptr)(char);

                  };

                  //——————-

                  int main()

                  {

                    class_a a;

                    class_b b;

                    a.fptr = &class_b::f;

                    (b.*a.fptr)(‘a’);

                    return 0;

                  }


                //nikson



                Сообщ.
                #7

                ,
                19.07.06, 12:30

                  Большое спасибо всем ответившим!

                  Несколько комментариев, зачем такое понадобилось. Программа предназначена для микроконтроллера, у прибора будет ЖКИ, и необходимо обеспечить графический интерфейс с пользователем. Для этого решил сделать набор простеньких классов а-ля Билдер — кнопочки, надписи итд. Получается, в программе есть *чисто программные* блоки (те самые графические элементы), а есть аппаратно-зависимые (работа с памятью, клавиатурой итд итп). Логично было бы их разделить. В самом деле, например, классу _надпись_ при отрисовке совершенно не надо знать, откуда и каким образом берётся массив байт с изображением (в разных устройствах может же быть по-разному) — ему просто подавай функцию, которая на заданный символ вернёт указатель на буфер (а сама реализует связь с памятью, обмен данными итд). Вот такую функцию я сделал в классе _микросхема_памяти_, образно говоря. При попытке подсунуть её классу _надпись_ и возник вопрос :)

                  Поэтому наиболее подходящий вариант от Flex Ferrum с использованием boost:: — почитал доки — вроде бы в самый раз будет. Если удастся это использовать и код особо не увеличится в размерах — будет просто супер!

                  В принципе, можно попробовать сделать статическую функцию, но как это повлияет на работу — надо будет ещё подумать.

                  Ну, а использовать внутри класса с указателем хоть какое-нибудь упоминание о другом классе (напр, в типе указателя) не хотелось бы — нарушается принцип независмости, из-за которого всё это и было затеяно.

                  ЗЫ. тему не закрываю, а вдруг с boost сам не разберусь, тогда ещё поспрашиваю :)


                  trainer



                  Сообщ.
                  #8

                  ,
                  19.07.06, 12:40

                    boost в мелкоконтроллере — довольно смело. :)


                    Flex Ferrum



                    Сообщ.
                    #9

                    ,
                    19.07.06, 12:53

                      Цитата trainer @ 19.07.06, 12:40

                      boost в мелкоконтроллере — довольно смело.

                      Я думаю, от компилятора зависит. bind/function разворачиваются оптимизатором очень даже неплохо.


                      trainer



                      Сообщ.
                      #10

                      ,
                      19.07.06, 14:40

                        Там(в function) исключения вроде используются, а в них — std::string.


                        Unreal Man



                        Сообщ.
                        #11

                        ,
                        19.07.06, 15:08

                          Цитата //nikson @ 19.07.06, 12:30

                          В принципе, можно попробовать сделать статическую функцию, но как это повлияет на работу — надо будет ещё подумать.

                          Дык всё зависит от того, что ты хочешь сделать. Если твоя функция class_b::f работает с данными уже существующего объекта типа class_b, то тогда её не надо делать статической. Если же тебе нужен просто аналог глобальной функции с правом доступа к закрытым членам объектов типа class_b, используемых где-то внутри этой функции, либо ты просто хочешь выразить принадлежность этой функции к данном классу (хотя по сути её можно было бы сделать глобальной), то тогда следует использовать статическую функцию. Наконец, может ты вообще захотел сгруппировать глобальные функции в некую именованную совокупность, но тогда для этого лучше подходит пространство имён, а не класс.

                          P.S. С бустом с таким знанием языка работать не советую :-‎)

                          Guru

                          ElcnU



                          Сообщ.
                          #12

                          ,
                          22.07.06, 08:55

                            Цитата //nikson, 19.07.2006, 2:37:59, 1182897

                            ЗЫ. компилятор используется IAR 3.21, но стандарты языка везде одинаковы…

                            под какой контроллер?
                            при описание класса IAR сожрал много памяти (работали с ATMeag8) :yes:


                            //nikson



                            Сообщ.
                            #13

                            ,
                            22.07.06, 11:34

                              Цитата

                              под какой контроллер?

                              msp430f149. на борту 60кб — пока ещё место есть :)


                              p_kolya



                              Сообщ.
                              #14

                              ,
                              24.07.06, 04:31

                                Ой… а чем для контроллера Си не устаривает? ИМХО для таких целей Си куда более пригоден, чем Си++.

                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)

                                0 пользователей:

                                • Предыдущая тема
                                • C/C++: Общие вопросы
                                • Следующая тема

                                Рейтинг@Mail.ru

                                [ Script execution time: 0,0446 ]   [ 16 queries used ]   [ Generated: 9.02.23, 11:54 GMT ]  

                                therom

                                1

                                Ссылки на функции класса

                                30.09.2008, 16:21. Показов 8147. Ответов 10

                                Метки нет (Все метки)


                                Задача:
                                В классе иметь массив ссылок на функции этого класса, чтобы вызывать их по номеру из массива.
                                Также в классе должна присутствовать функция обработки массива с целью получения ссылки на функции (по номеру в массиве) и их вызова.
                                Например: нужно вызвать функцию №2 класса MyClass……..

                                C++
                                1
                                2
                                3
                                4
                                5
                                6
                                7
                                8
                                9
                                10
                                11
                                12
                                13
                                14
                                15
                                16
                                17
                                
                                typedef void (*PF)(void); //Это для ссылки на функцию
                                // Есть класс:
                                class MyClass
                                {
                                public:
                                void func1(void){}
                                void func2(void){}
                                 
                                PF massiv[2]; // создаем массив ссылок для функций 
                                 
                                MyClass(void) // Конструктор
                                {
                                // в конструкторе присваиваем ссылкам адреса функций
                                massiv[0]=&func1;
                                massiv[1]=&func2;
                                }
                                };

                                Выскакивает ошибка в строках конструктора:
                                Error[Pe144]: a value of type «void (__nearfunc __version_3 MyClass::*)(void)» cannot be used to initialize an entity of type «PF»

                                Насколько я понял: на стадии конструирования класса еще не известны точные адреса функций

                                Приняв это предположение как факт, я попытался передать конструктору адрес класса:

                                C++
                                1
                                2
                                3
                                4
                                5
                                6
                                
                                MyClass(MyClass* adres) // Конструктор
                                {
                                // в конструкторе присваиваем ссылкам адреса функций
                                massiv[0]=&adres->func1;
                                massiv[1]=&adres->func2;
                                }

                                Теперь выскочила друкая ошибка:
                                Error[Pe300]: a pointer to a bound function may only be used to call the function

                                Как правильно реализовать задачу?

                                __________________
                                Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь

                                Супер-модератор

                                8781 / 2532 / 144

                                Регистрация: 07.03.2007

                                Сообщений: 11,873

                                30.09.2008, 16:30

                                2

                                я писал так, правда это в билдере:

                                Код

                                .h:
                                       void __fastcall CallView(AnsiString Type, AnsiString Caption);
                                       void __fastcall CallViewP(AnsiString Type, AnsiString Caption);
                                       void __fastcall (__closure* Func[2])(AnsiString, AnsiString);
                                .cpp:
                                  Func[0] = &CallView;
                                  Func[1] = &CallViewP;

                                а в других ide __closure не надо, вроде так читал по справке…

                                Код

                                typedef void (*PF)(void); //Это для ссылки на функцию
                                void func1(void){}
                                void func2(void){}
                                // Есть класс:
                                class MyClass
                                {
                                public:
                                
                                PF massiv[2]; // создаем массив ссылок для функций 
                                
                                MyClass(void) // Конструктор
                                {
                                // в конструкторе присваиваем ссылкам адреса функций
                                massiv[0]=&func1;
                                massiv[1]=&func2;
                                }
                                };

                                а у себя попробуй вынести реализацию методов отдельно от класса… должно сработать…



                                0



                                Почетный модератор

                                7388 / 2634 / 281

                                Регистрация: 29.07.2006

                                Сообщений: 13,696

                                30.09.2008, 16:37

                                3

                                Код

                                . . .
                                void (MyClass::*massiv[2])(void); // создаем массив ссылок для функций 
                                
                                MyClass(void) // Конструктор
                                {
                                // в конструкторе присваиваем ссылкам адреса функций
                                massiv[0]=&MyClass::func1;
                                massiv[1]=&MyClass::func2;
                                . . .



                                0



                                Эксперт С++

                                2254 / 769 / 25

                                Регистрация: 27.05.2008

                                Сообщений: 1,496

                                30.09.2008, 16:40

                                4

                                Есть огромная разница между функциями,и функциями- членами класса. Функции,описанные в классе,неявно принимают как параметр указатель на класс. Поэтому твое описание типа PF заведомо не рабочее.

                                Используй такую форму записи:

                                Код

                                void (MyClass::*PF)(void);



                                0



                                Супер-модератор

                                8781 / 2532 / 144

                                Регистрация: 07.03.2007

                                Сообщений: 11,873

                                30.09.2008, 17:03

                                5

                                я тут заметил, что в разных компиляторах разная форма написания такого рода массивов, ты на чем пишешь?
                                вот так работает в code block:

                                Код

                                typedef void (*PF)(void); 
                                class MyClass
                                {
                                public:
                                  static void MyClass::func1(void){ cout<<"func1"<<endl;};
                                  static void MyClass::func2(void){ cout<<"func2"<<endl;};
                                  PF massiv[2]; 
                                  MyClass(void) {
                                    massiv[0]=&func1;
                                    massiv[1]=&func2;
                                  }
                                };



                                0



                                therom

                                30.09.2008, 19:59

                                6

                                Далее следует еще одна проблема:
                                В классе есть функция, вызывающая функции класса по их номеру:

                                Код

                                void execute(char number)
                                {
                                (this->*massiv[number])();
                                }

                                Сдесь все ок.

                                Вызов извне этого обработчика выглядит так:

                                Код

                                MyClass myclass;
                                char number=1;
                                myclass.execute(number);

                                И сдесь все ок.

                                Проблема возникает, если у меня несколько классов и все разные, а вызывать надо по номеру класса и номеру функции в классе.
                                Не получается создать массив указателей на разные классы и через него вызывать класс->функцию

                                10 / 10 / 2

                                Регистрация: 18.08.2008

                                Сообщений: 127

                                30.09.2008, 22:38

                                7

                                Цитата
                                Сообщение от therom
                                Посмотреть сообщение

                                Не получается создать массив указателей на разные классы и через него вызывать класс->функцию

                                так не создавай массив создавай список .

                                а вообще массив из разнородных элементов никогда не получается .
                                а указатели на разные классы и есть разнородные элементы .



                                0



                                Sined

                                9 / 7 / 3

                                Регистрация: 30.08.2008

                                Сообщений: 120

                                01.10.2008, 00:57

                                8

                                Цитата
                                Сообщение от qwone
                                Посмотреть сообщение

                                а вообще массив из разнородных элементов никогда не получается .

                                Почему не получиться?

                                Вот пример:

                                C++
                                1
                                2
                                3
                                4
                                5
                                6
                                7
                                8
                                9
                                10
                                11
                                12
                                13
                                14
                                15
                                16
                                17
                                18
                                19
                                20
                                21
                                22
                                23
                                24
                                25
                                26
                                27
                                28
                                29
                                30
                                31
                                32
                                33
                                34
                                35
                                36
                                37
                                38
                                39
                                40
                                41
                                42
                                43
                                44
                                45
                                46
                                47
                                48
                                49
                                50
                                51
                                52
                                53
                                54
                                55
                                56
                                57
                                58
                                59
                                60
                                61
                                62
                                63
                                
                                class Base
                                {
                                public:
                                    virtual void Test1()=0;
                                    virtual void Test2()=0;
                                };
                                 
                                class First:public Base
                                {
                                public:
                                    void Test1()
                                    {
                                        printf("Test1 from Firstn");
                                    }
                                    void Test2()
                                    {
                                        printf("Test2 from Firstn");
                                    }
                                };
                                 
                                class Second:public Base
                                {
                                public:
                                    void Test1()
                                    {
                                        printf("Test1 from Secondn");
                                    }
                                    void Test2()
                                    {
                                        printf("Test2 from Secondn");
                                    }
                                };
                                 
                                void main()
                                {
                                    void *a[2];
                                    Base *base1=new First();
                                    Base *base2=new Second();
                                    a[0]=base1;
                                    a[1]=base2;
                                    if(dynamic_cast<First*>((Base*)(a[0])))
                                    {
                                        reinterpret_cast<First*>(a[0])->Test1();
                                        reinterpret_cast<First*>(a[0])->Test2();
                                    }
                                    else
                                    {
                                        reinterpret_cast<Second*>(a[0])->Test1();
                                        reinterpret_cast<Second*>(a[0])->Test2();
                                    }
                                    if(dynamic_cast<Second*>((Base*)(a[1])))
                                    {
                                        reinterpret_cast<First*>(a[1])->Test1();
                                        reinterpret_cast<First*>(a[1])->Test2();
                                    }
                                    else
                                    {
                                        reinterpret_cast<Second*>(a[1])->Test1();
                                        reinterpret_cast<Second*>(a[1])->Test2();
                                    }
                                    delete base1;
                                    delete base2;
                                }

                                Правда заумно, но работает!!!



                                0



                                10 / 10 / 2

                                Регистрация: 18.08.2008

                                Сообщений: 127

                                01.10.2008, 18:43

                                9

                                это не разнородные , это родственные , да и то на общую (базовую) часть . Но именно разнородные . Ведь ты это спрашивал?



                                0



                                9 / 7 / 3

                                Регистрация: 30.08.2008

                                Сообщений: 120

                                02.10.2008, 00:42

                                10

                                Цитата
                                Сообщение от qwone
                                Посмотреть сообщение

                                это не разнородные , это родственные…

                                Может я и путаю, «разнородные» и «родственные», но классы та разные, и функции я могу описать по-разному, единственное что интерфейс у классов одинаковый.



                                0



                                drfaust

                                550 / 383 / 125

                                Регистрация: 02.10.2008

                                Сообщений: 1,553

                                Записей в блоге: 1

                                02.10.2008, 22:52

                                11

                                Согласен с Sined`ом: если хочеш сделать структуру классов (массив или какую-либо динамику (список, дерево и т.д.)), то работай только через базоваый класс. Вопрос: как полутить доступ к указателям на функции-члены класса из глобального пространства имён: main. Например:

                                C++
                                1
                                2
                                3
                                4
                                5
                                6
                                7
                                8
                                9
                                10
                                11
                                12
                                13
                                14
                                15
                                16
                                17
                                18
                                19
                                20
                                21
                                22
                                23
                                24
                                25
                                26
                                27
                                28
                                29
                                30
                                31
                                32
                                33
                                
                                # include "stdlib.h"
                                 
                                class Base //базовый класс - нужен для "общности" классов (поэтому pure virtual)
                                {public:
                                   virtual int value()=0; // "вес" этого класса
                                };
                                 
                                class A: public Base //один потомок
                                {public:
                                  int value(); // вычисляется по одному Палгоритму :)
                                };
                                 
                                class B: public Base //другой потомок
                                { public:
                                  int value(); // вычисляется по другому алгоритму
                                };
                                 
                                Base array[234]={...,...,...}; // какой-то массив классов (и A, и B)
                                 
                                #typedef int (*PF)(void); //Это для ссылки на функцию
                                 
                                void PrintLess(PF func1, PF func2); //что-то делает за счёт func1 и func2
                                 
                                int main(int,char**)
                                {
                                 PrintLess(PF func1, PF func2);
                                 return 0;
                                }
                                 
                                void PrintLess(PF func1, PF func2)
                                {
                                ....
                                }

                                Такая ситуация возникает если используешь библиотечные С-функции применительно к функциям-членам классов: была проблема установить обработчик прерывания на функцию-член «стандартным способом»: setvect() в BC 3.1 для MS DOS. Пришлось решать через функцию-static-член и один глобальный указатель на неё… Коряво, не красиво, но это единственное,что я нашёл



                                0



                                Я работаю над домашним заданием для своего C + + class и столкнулся с проблемой, заключающейся в том, что я не могу понять, что делаю неправильно.

                                Следует отметить, что разделение файлов необходимо, и я понимаю, что это было бы намного проще, если бы я просто создал структуру AttackStyles внутри main и вообще отказаться от дополнительного файла класса.

                                Основа моей проблемы в том, что я не могу перебирать массив классов и извлекать базовые данные. Вот код:

                                // AttackStyles.h
                                #ifndef ATTACKSTYLES_H
                                #define ATTACKSTYLES_H
                                #include <iostream>
                                #include <string>
                                
                                using namespace std;
                                
                                class AttackStyles
                                {
                                private:
                                    int styleId;
                                    string styleName;
                                
                                public:
                                    // Constructors
                                    AttackStyles();  // default
                                    AttackStyles(int, string);
                                
                                    // Destructor
                                    ~AttackStyles();
                                
                                    // Mutators
                                    void setStyleId(int);
                                    void setStyleName(string);  
                                
                                    // Accessors
                                    int getStyleId();
                                    string getStyleName();  
                                
                                    // Functions
                                
                                };
                                #endif
                                
                                
                                /////////////////////////////////////////////////////////
                                // AttackStyles.cpp
                                #include <iostream>
                                #include <string>
                                #include "AttackStyles.h"
                                using namespace std;
                                
                                
                                // Default Constructor
                                AttackStyles::AttackStyles()    
                                {}
                                
                                // Overloaded Constructor
                                AttackStyles::AttackStyles(int i, string n)
                                {
                                    setStyleId(i);
                                    setStyleName(n);
                                }
                                
                                // Destructor
                                AttackStyles::~AttackStyles()    
                                {}
                                
                                // Mutator
                                void AttackStyles::setStyleId(int i)
                                {
                                    styleId = i;
                                }
                                
                                void AttackStyles::setStyleName(string n)
                                {
                                    styleName = n;
                                }
                                
                                // Accessors
                                int AttackStyles::getStyleId()
                                {
                                    return styleId;
                                }
                                
                                string AttackStyles::getStyleName()
                                {
                                    return styleName;
                                }
                                
                                
                                //////////////////////////////////////////////
                                // main.cpp
                                #include <cstdlib>
                                #include <iostream>
                                #include <string>
                                #include "attackStyles.h"
                                
                                using namespace std;
                                
                                int main()
                                {
                                    const int STYLE_COUNT = 3;
                                    AttackStyles asa[STYLE_COUNT] = {AttackStyles(1, "First"), 
                                                                     AttackStyles(2, "Second"), 
                                                                     AttackStyles(3, "Third")};
                                
                                    // Pointer for the array
                                    AttackStyles *ptrAsa = asa;
                                
                                    for (int i = 0; i <= 2; i++)
                                    {
                                        cout << "Style Id:t" << ptrAsa->getStyleId << endl;
                                        cout << "Style Name:t" << ptrAsa->getStyleName << endl;
                                        ptrAsa++;
                                    }
                                
                                    system("PAUSE");
                                    return EXIT_SUCCESS;
                                }
                                

                                У меня вопрос, почему я получаю сообщение об ошибке:

                                  "a pointer to a bound function may only be used to call the function"
                                

                                на обоих ptrAsa->getStyleId и ptrAsa->getStyleName?

                                Я не могу понять, что с этим не так!

                                Понравилась статья? Поделить с друзьями:

                                Читайте также:

                              • Error a jnj error has occurred
                              • Error a jni error has occurred please check your installation and try again сервер майнкрафт
                              • Error a jni error has occurred please check your installation and try again ошибка
                              • Error a jni error has occurred please check your installation and try again как решить
                              • Error a jni error has occurred please check your installation and try again как исправить

                              • 0 0 голоса
                                Рейтинг статьи
                                Подписаться
                                Уведомить о
                                guest

                                0 комментариев
                                Старые
                                Новые Популярные
                                Межтекстовые Отзывы
                                Посмотреть все комментарии