如何使用指向C ++方法的指针?

时间:2013-10-30 12:08:47

标签: c++ function-pointers static-methods static-members

我想在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'

3 个答案:

答案 0 :(得分: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 ++ 11 std::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函数是Orbit中Lightness Races指出的函数,则不能使用成员函数指针。然而,上面列表中的第一个案例是错误的,因为第二个论点完全不同。

答案 1 :(得分: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)'

因此,您可以重新定义触摸,以便返回指向独立函数的指针,并使用参数更改它的行为。或者,将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;

答案 2 :(得分: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;

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