簡體   English   中英

非靜態成員函數的無效使用 - 類成員函數調用另一個類成員函數

[英]Invalid use of non-static member function - Class Member Function Calling Another Class Member Function

當我嘗試編譯時,我不斷收到此消息:

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->createTask()調用this->OtherMain()有什么問題嗎?

void(*task_main)()需要一個指向函數的指針。 你試圖喂它void otherMain(); 這是一個類方法並且有一個隱藏的this參數。

這東西變得有點古怪。 這是一篇關於一些壞處以及如何避免它的好文章。

你將不得不重新思考如何做到這一點。 您可以使用static void task_runner(void * userparam)方法(沒有this )和可以由靜態方法轉換的用戶參數來提供一個TaskManager ,您可以在其上調用otherMain 您可以將void(*task_main)()轉換為void(TaskManager::*task_main)()並且您仍然必須提供一個TaskManager來調用方法指針。

這是一項非常糟糕的業務,但我可以讓您對探索std::bind感興趣嗎?

編輯

任務運行器是這樣的:

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
}

createTask()的第二個參數是:

 void(*task_main)()

這是一個指向返回void的函數的指針。

您正在通過:

 this->otherMain

otherMain不是返回void的函數。 它是一個返回void的類成員。 類成員與函數並不完全相同。

與返回 void 的類方法匹配的createTask的正確參數類型是:

void  (TaskManager::*task_main)()

otherMain類方法可以簡單地傳遞:

&TaskManager::otherMain

這將解決此函數調用的編譯錯誤的直接問題。

但是,您現在可能會遇到一個新的、不同的問題。 您現有的代碼嘗試將函數指針填充到類似於 CPU 寄存器的內容中。

好吧,您不再有函數指針了。 您現在有一個類方法指針。 現有代碼能否正常工作取決於您的 C++ 實現。 可能不是,但這將是一個不同的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM