Pages: [1]   Go Down
Author Topic: C++ problem with pure virtual method  (Read 5003 times)
0 Members and 1 Guest are viewing this topic.
Florida, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 146
meow!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I am a fairly experienced C++ programmer, but this has me stumped.  I am trying to make a generic class for button debouncing, and then derive from that a class specific to an analog touch sensor I made.  But when my base class DebouncedButton tries to call a pure virtual method isButtonPressed(), the compiler barks at me like an angry German Shepherd:
 
o: In function `DebouncedButton::update()':
undefined reference to `__cxa_pure_virtual'
 
The line of code it does not like is marked with "//!!!!!" below.  Am I doing something wrong, or does this compiler not support pure virtual methods?
 
Code:
/*
    touch_sensor.pde  -  Don Cross  -  http://cosinekitty.com
    
    Experiment with interfacing darlington-pair touch sensor to analog input on atmega8.
*/

//-------------------------------------------------------------------------------------------------

class DebouncedButton {
public:
    DebouncedButton (unsigned _debounceTimeInMilliseconds):
        stableButtonState (false),  // assume button starts out released
        debounceTimeInMilliseconds (_debounceTimeInMilliseconds)
    {
    }

    void update()
    {
        // Check current sensor reading...
        bool sample = isButtonPressed();      //!!!!!
        unsigned long now = millis();

        // Is the current state different from the last stable state?
        if (sample == stableButtonState) {
            // might still be bouncing around, so restart debounce timer
            lastBounceTime = now;
        } else {
            unsigned long elapsed = now - lastBounceTime;
            if (elapsed > debounceTimeInMilliseconds) {
                // the state has changed, and appears stable, so toggle the state now...
                stableButtonState = sample;
                if (stableButtonState) {
                    onPress();
                } else {
                    onRelease();
                }
            }
        }
    }

    virtual bool isButtonPressed() = 0;     // derived class defines what it means for noisy button to be pressed
    virtual void onPress() = 0;             // action to take when debouncer says button is pressed
    virtual void onRelease() = 0;           // action to take when debouncer says button is realeased

private:
    bool            stableButtonState;      // false=button released, true=button pressed
    unsigned long   lastBounceTime;
    unsigned        debounceTimeInMilliseconds;
};


//-------------------------------------------------------------------------------------------------


const int TOUCH_THRESHOLD = 500;
class AnalogTouchSensor: public DebouncedButton {
public:
    AnalogTouchSensor (byte _analogInputPin, byte _digitalOutputPin):
        DebouncedButton (10),        // pass debounce time in milliseconds to DebouncedButton class
        analogInputPin (_analogInputPin),
        digitalOutputPin (_digitalOutputPin),
        digitalOutputState (false)
    {
        pinMode (digitalOutputPin, OUTPUT);
    }

    virtual bool isButtonPressed()
    {
        return analogRead(analogInputPin) < TOUCH_THRESHOLD;
    }

    virtual void onPress()
    {
        digitalOutputState = !digitalOutputState;
        digitalWrite (digitalOutputPin, digitalOutputState);
    }

    virtual void onRelease()
    {
        // do nothing
    }

private:
    byte    analogInputPin;
    byte    digitalOutputPin;
    byte    digitalOutputState;
};


//-------------------------------------------------------------------------------------------------


AnalogTouchSensor sensor(5, 13);     // monitor analog pin 5, toggle LED on pin 13


void setup()
{
}

void loop()
{
    sensor.update();
}

//-------------------------------------------------------------------------------------------------

/*
    $Log: touch_sensor.pde,v $
    Revision 1.1  2007/01/01 02:30:14  dcross
    Almost works, but needs debounce.

*/
Logged

Florida, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 146
meow!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

As a follow-up, I found a workaround:  I modified class DebouncedButton and replaced the following lines:

Code:
   virtual bool isButtonPressed() = 0;     // derived class defines what it means for noisy button to be pressed
    virtual void onPress() = 0;             // action to take when debouncer says button is pressed
    virtual void onRelease() = 0;           // action to take when debouncer says button is realeased

with these lines:

Code:
   virtual bool isButtonPressed()     // derived class defines what it means for noisy button to be pressed
    {
        return false;
    }

    virtual void onPress()             // action to take when debouncer says button is pressed
    {
    }

    virtual void onRelease()           // action to take when debouncer says button is realeased
    {
    }

The compiler no longer complains, and as a bonus, when I upload and run the sketch, it actually works!  So I can tell that my derived class methods are being called, not the base class, as is supposed to be the case.  Weird...
Logged

Forum Administrator
Cambridge, MA
Offline Offline
Faraday Member
*****
Karma: 11
Posts: 3538
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The C++ compiler for the AVR doesn't implement all of C++, so I can imagine that it doesn't support pure virtual functions.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 41
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am encountering the same error from the linker when trying to compile a sketch agains the Arduino library from SVN (pre 0016 code, i believe). All worked fine for versions up to 0014, but then they changed HardwareSerial ... CosineKitty, do you mind taking a look?

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1240829167
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 200
Posts: 12782
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If you're still curious, try defining the pure virtual methods before update...

Code:
// ...
    virtual bool isButtonPressed() = 0;     // derived class defines what it means for noisy button to be pressed
    virtual void onPress() = 0;             // action to take when debouncer says button is pressed
    virtual void onRelease() = 0;           // action to take when debouncer says button is realeased

// ...

void update()
// ...

Does that make any difference?

- Brian
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 41
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It turns out you have to define __cxa_pure_virtual() for pure virtual functions to work.

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=410870
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1207386508

And a long discussion, a good part of which I don't get:
http://www.mail-archive.com/avr-libc-dev@nongnu.org/msg01223.html
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 200
Posts: 12782
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

That's really odd.  I have a Sketch with a pure virtual function...

Code:
class TrdApplication
{
public:
  virtual void Run( bool& OkToSleep ) = 0;
};

...and I haven't had any problems.

I prefer declarations and code separated so that might make a difference.

The compiler / linker must think that you've created an instance of DebouncedButton.

Oh well.  I'm glad you found a solution.

- Brian
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 41
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
That's really odd.  I have a Sketch with a pure virtual function...

Indeed it is. Are you compiling this with the Arduino IDE? My problem is not the DebounceButton class, but this. Sorry for taking over this thread.
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 200
Posts: 12782
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Arduino 0015 IDE.

- Brian
Logged

Pages: [1]   Go Up
Jump to: