-1

我想在下面的wake_event中使用类方法指针,但是编译错误,我不想使用静态成员和方法,因为这个类的实例可能不止一个,这可能吗?我可以修改我的源代码吗?

class UncouplerController {
private:
    TouchSensor *touchSensor;
public:
    wakeup_t touched(wakeup_t data) {
        return UncouplerController::touchSensor->pressed();
    }

   const void uncoupling() {
       wait_event(&touched, 0);
   }
}

编译错误如下

/usr/local/bin/h8300-hitachi-hms-g++ -DCXX -fno-rtti -fno-exceptions -O2 -fno-builtin -fomit-frame-pointer -Wall -I/brickos/include -I/brickos/include/lnp -I. -I/brickos/boot  -c rcx1.C -o rcx1.o
In file included from rcx1.H:27,
                 from rcx1.C:21:
UncouplerController.H: In function `static wakeup_t UncouplerController::untouched(long unsigned int)':
UncouplerController.H:38: member `UncouplerController::touchSensor' is non-static but referenced as a static member
UncouplerController.H:62: at this point in file
UncouplerController.H:63: warning: control reaches end of non-void function `UncouplerController::untouched(long unsigned int)'
UncouplerController.H: In method `const void UncouplerController::uncoupling()':
UncouplerController.H:74: converting from `wakeup_t (UncouplerController::*)(long unsigned int)' to `wakeup_t (*)(long unsigned int)'
UncouplerController.H: In method `const void UncouplerController::coupling()': 
UncouplerController.H:99: converting from `wakeup_t (UncouplerController::*)(long unsigned int)' to `wakeup_t (*)(long unsigned int)'
UncouplerController.H: At top level:
UncouplerController.H:112: `class TouchSensor * UncouplerController::touchSensor' is not a static member of `class UncouplerController'
4

3 回答 3

1

这里要知道的是,指向成员函数指针与指向(独立)函数的指针不同。不同之处在于所有成员函数都有一个隐藏的第一个参数,即this函数中的指针。因此,您需要有一个对象实例才能真正调用成员函数指针。

只有static成员函数没有这个隐藏的第一个参数,因为它们没有this指针(静态成员函数用于整个类,而不是特定实例),因此可以用作普通函数指针。


成员函数指针的三种使用方式。

  • 第一种是使用静态成员函数,并为其提供一个参数,该参数将是指向实例的指针。当然,这只有在系统允许您向函数指针传递额外参数时才有效。如果(我只是在这里猜测)第二个参数wait_event是这样一个“userdata”指针,那么可以使用它:

    wait_event(&staticTouched, this);
    

    然后你创建一个调用真实函数的静态成员函数:

    static void staticTouched(void* instance)
    {
        static_cast<UncouplerController*>(instance)->touched();
    }
    
  • 第二种方法是如果是您的类的成员,在这种情况下,它实际上可以在调用成员函数时wait_event使用自己的指针:this

    void wait_event(void (UncouplerController::*func)(), ...)
    {
        // Do stuff...
    
        (this->func)();  // Call the member function pointer
    }
    
  • 第三种方法是使用新的 C++11std::function类,而不是成员函数指针。这将使事件处理系统更加通用,std::function可用于存储普通函数、静态成员函数、非静态成员函数和 lambda 表达式。除此之外,它与第二种情况非常相似:

    void wait_event(std::function<void()> func, ...)
    {
        // Do stuff...
    
        func();  // Call the function object
    }
    

    然后wait_event用成员函数指针调用,你使用std::bind

    wait_event(std::bind(&UncouplerController::touched, this), 0);
    

如果wait_event函数是 Lightness Races in Orbit 指出的函数,则不能使用成员函数指针。我上面列表中的第一个案例是错误的,因为第二个参数是完全不同的。

于 2013-10-30T12:11:41.883 回答
0

我同意约阿希姆的观点。另一方面,我会给你一些代码提示,让我知道是否适合你。

换行:

return UncouplerController::touchSensor->pressed();

经过:

return this->touchSensor->pressed();

wait_event 是一个独立的函数,你正在传递一个作为类成员的函数,这就是输出错误中以下行的原因:

UncouplerController.H:74: converting from `wakeup_t (UncouplerController::*)(long unsigned int)' to `wakeup_t (*)(long unsigned int)'

因此,您可以重新定义 touch 以返回一些指向独立函数的指针,并使用参数更改其行为。或者,将 wakeup_t 声明为独立函数并使其成为类的朋友。第二个看起来要容易得多。

让我知道是否有效。如果您发布更多代码,也许可以帮助您更多。

另一种方法是使用关键字“reinterpret_cast”,但我不推荐它。

好吧,您可以尝试以下方法:

// Define the type expected by  "wait_event"
typedef wakeup_t (*wake_func_ptr) (wakeup_t data);


class UncouplerController {

private:
    TouchSensor *touchSensor;

public:
    // Member for pointing the target functions.
    wake_func_ptr touched;
    wake_func_ptr untouched;

    UncouplerController(Sensor::Port sensorPort)
    {
        // This will rise a lot of warnings.
        // I strongly not recomend to do this.
        // But it seems to be a solution.
        touched = reinterpret_cast<wake_func_ptr>(&UncouplerController::touched_func);
        untouched = reinterpret_cast<wake_func_ptr>(&UncouplerController::untouched_func);

        touchSensor = new TouchSensor(sensorPort);
    }


    ~UncouplerController() {
        delete touchSensor;
    }

    wakeup_t touched_func(wakeup_t data) {
        return touchSensor->pressed();
    }

    wakeup_t untouched_func(wakeup_t data) {
        return touchSensor->pressed();
    }


    const void uncoupling() {
        wait_event(touched, 0);
        delay(UNCOUPLING_TIME1);
    }

    const void coupling() {
        wait_event(touched, 0);
        wait_event(untouched, 0);
        delay(COUPLING_TIME);
    }
};

// The purpose of this line isn't clear for me.
TouchSensor *UncouplerController::touchSensor;
于 2013-10-30T12:43:31.703 回答
0

这是我的代码,它有效。

class UncouplerController {
private:
    static TouchSensor *touchSensor;

public:
    UncouplerController(Sensor::Port sensorPort) {
        touchSensor = new TouchSensor(sensorPort);
    }
    ~UncouplerController() {
        delete touchSensor;
    }
    static wakeup_t touched(wakeup_t data) {
        return UncouplerController::touchSensor->pressed();
    }
    static wakeup_t untouched(wakeup_t data) {
        return !UncouplerController::touchSensor->pressed();
    }
    const void uncoupling() {
        wait_event(&UncouplerController::touched, 0);
        delay(UNCOUPLING_TIME1);
    }
    const void coupling() {
        wait_event(&UncouplerController::touched, 0);
        wait_event(&UncouplerController::untouched, 0);  
        delay(COUPLING_TIME);
    }
};

TouchSensor *UncouplerController::touchSensor;

我想知道是否没有使用静态成员或函数,并将它们全部移出类,我可以得到相同的结果!有人告诉我哪种方式更好吗?谢谢你的帮助。

于 2013-10-30T15:48:23.213 回答