Error: Reference to non-static member function must be called

Error: Reference to non-static member function must be called
0

Hi, I’m using cocos2d-x v4. I got this error on XCode. I tried to build an iOS project. Do you have any solution.

this->scheduleOnce(schedule_selector(SelectGameScene::startGameCallback),this, 0.0f, false);

Error: Reference to non-static member function must be called.

void* SelectGameScene::startGameCallback( **float** dt) {
Director::getInstance()->replaceScene(TransitionFade::create(TRANSITION_TIME, 
GameScene::createScene()));
}

What is the error?

I’ve just updated my question.

Is SelectGameScene static?

class SelectGameScene : public cocos2d::Layer
{

public :

static cocos2d::Scene* createScene();
}

Yes, createScene is a static method. So what should I do?

What is GameScene?

GameScene is a layer. GameScene is like an ordinary scene. On this screen you can select a level.

Scene* SelectGameScene::createScene()
{
    auto scene = Scene::create(); 
    auto layer = SelectGameScene::create();
    scene->addChild(layer);
    return scene;
}

bool SelectGameScene::init()
{
    if (!Layer::init())
    	return false;

  visibleSize = Director::getInstance()->getVisibleSize();
     this->setName("SelectGameScene");
 }

Does schedule_selector actually exist? The only thing I can see is SEL_SCHEDULE and the CC_SCHEDULE_SELECTOR macro.

Where is this->scheduleOnce(schedule_selector(SelectGameScene::startGameCallback),this, 0.0f, false); in your code? You haven’t shown the code where this call is happening.

Is that a static method?

Regardless though, you should probably avoid the SEL_SCHEDULE or anything related to it, since you have been provided with better way to set the callback.

void scheduleOnce(const std::function<void(float)>& callback, float delay, const std::string &key);

You can either do this:

scheduleOnce([](float dt) {
    Director::getInstance()->replaceScene(TransitionFade::create(TRANSITION_TIME, GameScene::createScene()));
}, delay, "YourKey");

or this:

scheduleOnce(std::bind(&SelectGameScene::startGameCallback, this, std::placeholders::_1), delay, "YourKey");

To reduce typing, add this to the top of the cpp file:
using namespace std::placeholders;

So, it would end up like this:

scheduleOnce(std::bind(&SelectGameScene::startGameCallback, this, _1), delay, "YourKey");

SelectGameScene::startGameCallback cannot be static.

Ok, let’s remove a schedule_selector for simplicity.

SelectGameScene::startGameCallback
Is that a static method? Actually it is not a static method. But I create SelectGameScene through a static method createScene().

class SelectGameScene : public cocos2d::Layer
{
public :
static cocos2d::Scene* createScene();
void onTouchEnded(cocos2d::Touch* touch, cocos2d::Event* event);
void startGameCallback( float dt);
}

Scene* SelectGameScene::createScene()

{

auto scene = Scene::create();

auto layer = SelectGameScene::create();

scene->addChild(layer);

return scene;

}

void SelectGameScene::onTouchEnded(Touch* touch, Event* event)
{
SelectGameScene::startGameCallback;
}

How do I create a SelectGameScene?
In the main Scene I called
Director::getInstance()->replaceScene(TransitionFade::create(TRANSITION_TIME, SelectGameScene::createScene()));

SelectGameScene::startGameCallback;
This line of code is produce an error “Reference to non-static member function must be called”

Is startGameCallback a static method. It isn’t. But I create SelectGameScene through a static method createScene(). So compiler think that all methods of this class are static. Is compiler right?

Just to help people reading your post, please format any code you paste (3 back-tick characters before and after the section of code).

Now, you still haven’t posted the code where you called the scheduleOnce(). It has nothing to do with the fact that you’re creating a scene using SelectGameScene::createScene(), unless you’re trying to use the ‘this’ pointer inside it, since it’s invalid.

So again, show the entire code chain till that leads to the scheduleOnce() call, not just bits and pieces, because it’s really hard to help when it’s a guessing game.

Is startGameCallback a static method. It isn’t. But I create SelectGameScene through a static method createScene(). So compiler think that all methods of this class are static. That’s why I can’t get a reference.
Error is : “Reference to non-static member function must be called”


void MainMenuScene::startCallback(Ref* pSender)
{
	Director::getInstance()->replaceScene(TransitionFade::create(TRANSITION_TIME, SelectGameScene::createScene()));
}

class SelectGameScene : public cocos2d::Layer
{
public:
    static cocos2d::Scene* createScene();
    virtual bool init();  
    void onTouchEnded(cocos2d::Touch* touch, cocos2d::Event* event);
    void startGameCallback( float dt);
}

Scene* SelectGameScene::createScene()
{
    auto scene = Scene::create(); 
	auto layer = SelectGameScene::create();
    scene->addChild(layer);
    return scene;
}

bool SelectGameScene::init()
{
	if (!Layer::init())
		return false;

	visibleSize = Director::getInstance()->getVisibleSize();
    this->setName("SelectGameScene");
}

void SelectGameScene::onTouchEnded(Touch* touch, Event* event)
{
	this->scheduleOnce(schedule_selector(SelectGameScene::startGameCallback),this, 0.0f, false);
}

void SelectGameScene::startGameCallback(float dt)
{
	Director::getInstance()->replaceScene(TransitionFade::create(TRANSITION_TIME, GameScene::createScene()));
}

Where

typedef void (Ref::*SEL_SCHEDULE)(float);
#define CC_SCHEDULE_SELECTOR(_SELECTOR) static_cast<cocos2d::SEL_SCHEDULE>(&_SELECTOR)

void Node::scheduleOnce(SEL_SCHEDULE selector, float delay)
{
    this->schedule(selector, 0.0f, 0, delay);
}

void Node::schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay)
{
    CCASSERT( selector, "Argument must be non-nil");
    CCASSERT( interval >=0, "Argument must be positive");

    _scheduler->schedule(selector, this, interval , repeat, delay, !_running);
}

void Scheduler::schedule(SEL_SCHEDULE selector, Ref *target, float interval, unsigned int repeat, float delay, bool paused)
{
    CCASSERT(target, "Argument target must be non-nullptr");
    
    tHashTimerEntry *element = nullptr;
    HASH_FIND_PTR(_hashForTimers, &target, element);
    
    if (! element)
    {
        element = (tHashTimerEntry *)calloc(sizeof(*element), 1);
        element->target = target;
        
        HASH_ADD_PTR(_hashForTimers, target, element);
        
        // Is this the 1st element ? Then set the pause level to all the selectors of this target
        element->paused = paused;
    }
    else
    {
        CCASSERT(element->paused == paused, "element's paused should be paused.");
    }
    
    if (element->timers == nullptr)
    {
        element->timers = ccArrayNew(10);
    }
    else
    {
        for (int i = 0; i < element->timers->num; ++i)
        {
            TimerTargetSelector *timer = dynamic_cast<TimerTargetSelector*>(element->timers->arr[i]);
            
            if (timer && !timer->isExhausted() && selector == timer->getSelector())
            {
                CCLOG("CCScheduler#schedule. Reiniting timer with interval %.4f, repeat %u, delay %.4f", interval, repeat, delay);
                timer->setupTimerWithInterval(interval, repeat, delay);
                return;
            }
        }
        ccArrayEnsureExtraCapacity(element->timers, 1);
    }
    
    TimerTargetSelector *timer = new (std::nothrow) TimerTargetSelector();
    timer->initWithSelector(this, selector, target, interval, repeat, delay);
    ccArrayAppendObject(element->timers, timer);
    timer->release();
}

XCode compiler thinks that SelectGameScene::startGameCallback is static method but it is just a member function pointer. So I decide to rewrite this statement.

this->scheduleOnce(schedule_selector(SelectGameScene::startGameCallback),0.0f);

I can change schedule_selector to

static_cast<cocos2d::SEL_SCHEDULE>(&_SELECTOR) 

so

auto funPointer = static_cast<cocos2d::SEL_SCHEDULE>(&SelectGameScene::startGameCallback);
this->scheduleOnce(funPointer, 0.0f);

That’s the important bit of code. You’re not calling scheduleOnce from a static function, as SelectGameScene::onTouchEnded is not a static, so you’re focusing on the wrong issue.

The problem is the schedule_selector (again, I don’t know what this is), and the fact that you’re not passing an address of the member function.

Does this mean you got it working?

Once again, I strongly recommend that you do not use those methods, but use this instead:

void scheduleOnce(const std::function<void(float)>& callback, float delay, const std::string &key);

The code would be a lot clearer in what it is you’re trying to do, along with future-proofing your code, in case the SEL_SCHEDULE and CC_SCHEDULE_SELECTOR ever get removed.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.