无效使用非静态成员函数 - 类成员函数调用另一个类成员函数

时间:2016-09-10 00:16:06

标签: c++ non-static

我在尝试编译时不断收到此消息:

task.c++:54:102: error: invalid use of non-static member function
      this->createTask(&otherTask, this->otherMain, mainTask.regs.eflags, (uint32_t*)mainTask.regs.cr3);

这是我的task.c ++函数:

#include "task.h"



static task_q *runningTask;
static task_q mainTask;
static task_q otherTask;
static PhyiscalMemoryManager *pmm_task;
static  Heap *heap_task;



extern void switch_task_a();

TaskManager::TaskManager(Heap *heap)
{
 heap_task = heap;
}
TaskManager::~TaskManager()
{}

Task::Task()
{}

Task::~Task()
{}
void TaskManager::otherMain()
{
        printf("Hello multitasking world!"); // Not implemented here...
        preempt();
}


void TaskManager::createTask(task_q* task, void(*task_main)(), uint32_t flags, uint32_t* pageDir)
{
        task->regs.ebx = 0;
        task->regs.ecx = 0;
        task->regs.edx = 0;
        task->regs.esi = 0;
        task->regs.edi = 0;
        task->regs.eflags = flags;
        task->regs.eip = (uint32_t) task_main;
        task->regs.cr3 = (uint32_t) pageDir;
        task->regs.esp = (uint32_t) (heap_task->k_malloc(TASK_STACK_SIZE)) + 0x1000; // Not implemented here
        task->next = 0;
}

void TaskManager::init_tasking()
{
     // Get EFLAGS and CR3
        __asm __volatile("movl %%cr3, %%eax; movl %%eax, %0;":"=m"(mainTask.regs.cr3)::"%eax");
        __asm __volatile("pushfl; movl (%%esp), %%eax; movl %%eax, %0; popfl;":"=m"(mainTask.regs.eflags)::"%eax");

        this->createTask(&otherTask, this->otherMain, mainTask.regs.eflags, (uint32_t*)mainTask.regs.cr3);
        mainTask.next = &otherTask;
        otherTask.next = &mainTask;

        runningTask = &mainTask;
}

void TaskManager::switchTask(Registers *old, Registers *new_)
{
    switch_task_a();
}

void TaskManager::preempt()
{
    task_q *last = runningTask;
    runningTask = runningTask->next;
    switchTask(&last->regs, &runningTask->regs);
}

这是我的task.h:

#ifndef _TASK_H_
#define _TASK_H_ 1

#include <stdarg.h>
#include <stdint.h>
#include "gdt.h"
#include "stdio.h"
#include "heap.h"
#include "pmm.h"

#define TASK_STACK_SIZE 0x2000

typedef struct {
        uint32_t eax, ebx, ecx, edx, esi, edi,
                 esp, ebp, eip, eflags, cr3;
} Registers;

typedef struct task_q {
            Registers regs;
            struct task_q *next;
} task_q;

class Task
{
    friend class TaskManager;
public:
    Task();
    ~Task();
private:
};

class TaskManager
{
public:
    TaskManager(Heap *heap);
    ~TaskManager();
    void init_tasking();
    static void createTask(task_q* task, void(*task_main)(), uint32_t flags, uint32_t* pageDir);
    void preempt();
private:
    void switchTask(Registers *old, Registers *new_);
    void otherMain();
};

#endif

this->OtherMain()内调用this->createTask()是否有问题?

2 个答案:

答案 0 :(得分:0)

void(*task_main)()期待指向函数的指针。您尝试将其void otherMain();作为类方法并且具有隐藏的this参数。

这个东西有点令人讨厌。 Here is a great write-up on some of the badness and how to avoid it.

您将不得不重新考虑如何执行此操作。您可以使用static void task_runner(void * userparam)方法(无this)和静态方法可以投射的用户参数来提供TaskManager,您可以在其上调用otherMain。您可以将void(*task_main)()转换为void(TaskManager::*task_main)(),并且您仍然需要提供TaskManager来调用方法指针。

这是一项非常讨厌的事业,but can I interest you in exploring std::bind instead?

修改

任务运行员就是这样的:

class taskRunner
{
public:
    virtual execute() = 0;
    static void task_runner(void * userparam)
    {
        taskRunner* task = (taskRunner*)userparam;
        task->execute();
    }
};

下行是您尝试运行的所有内容必须是继承taskRunner并实现execute的类,并且必须跟踪userparam。涉及非平凡的努力,但到底是什么。看起来你自己写了一个操作系统。全面的非常重要的努力。

对你来说可能更好,它将抽象提升到一个级别,只接受自由函数和静态方法。让正在运行的函数判断它是否是一个类。

这意味着otherMain不能成为TaskManager的成员,除非它是静态的,这需要重新编写TaskManager以允许横切行为,例如任务的睡眠能力,产生时间片,以及在不知道TaskManager内部的情况下调用其他操作系统的好东西。

otherMain可能只是

void otherMain()
{
    printf("Hello multitasking world!"); 
    yield(); // a free function that calls into the system's TaskManager to preempt
}

答案 1 :(得分:0)

createTask()的第二个参数是:

 void(*task_main)()

这是一个指向返回void的函数的指针。

你传递的是:

 this->otherMain

otherMain不是返回void的函数。它是一个返回void的类成员。类成员与函数不完全相同。

createTask的正确参数类型,以匹配返回void的类方法:

void  (TaskManager::*task_main)()

并且otherMain类方法可以简单地传递:

&TaskManager::otherMain

这将解决此函数调用的编译错误的直接问题。

但是,您现在可能会遇到一个新的不同问题。您现有的代码会尝试将函数指针填充到类似于CPU寄存器的内容中。

好吧,你不再拥有一个功能指针。你现在有一个类方法指针。现有代码是否可以正常工作取决于您的C ++实现。可能不是,但这将是一个不同的问题。