I have a post about this problem.
Basically you cannot attach a class function with attachInterrupt because of the hidden "this" pointer which needs to be supplied to a (non-static) class function, where "this" is the particular instance of the class. You can work around it like this:
class myClass
{
static volatile bool switchChanged; // declare
public:
void begin ()
{
pinMode (2, INPUT_PULLUP);
attachInterrupt (0, switchPressed, CHANGE);
} // end of myClass::begin
static void switchPressed ()
{
switchChanged = true;
} // end of myClass::switchPressed
}; // end of class myClass
volatile bool myClass::switchChanged; // define
myClass foo; // make an instance of myClass
void setup ()
{
foo.begin ();
} // end of setup
void loop ()
{
// whatever
} // end of loop
But that isn't great because, as you observed, you are really downgrading the class to use a static boolean.
Another way of doing it is to write "glue" routines, like this:
class myClass
{
volatile bool switchChanged;
static myClass * instances [2];
static void switchPressedExt0 ()
{
if (myClass::instances [0] != NULL)
myClass::instances [0]->switchPressed ();
} // end of myClass::switchPressedExt0
static void switchPressedExt1 ()
{
if (myClass::instances [1] != NULL)
myClass::instances [1]->switchPressed ();
} // end of myClass::switchPressedExt1
public:
void begin (const byte whichPin)
{
pinMode (whichPin, INPUT_PULLUP);
switch (whichPin)
{
case 2:
attachInterrupt (0, switchPressedExt0, CHANGE);
instances [0] = this;
break;
case 3:
attachInterrupt (1, switchPressedExt1, CHANGE);
instances [1] = this;
break;
} // end of switch
} // end of myClass::begin
void switchPressed ()
{
switchChanged = true;
}
}; // end of class myClass
myClass * myClass::instances [2] = { NULL, NULL };
// instances of our class
myClass foo;
myClass bar;
void setup ()
{
foo.begin (2); // pin D2
bar.begin (3); // pin D3
} // end of setup
void loop ()
{
// whatever
} // end of loop
That's still not a great solution, but it might give you some ideas.
Your fundamental problem is that classes, by their nature, can be instantiated many times, however you only have a small, fixed, number of interrupts on the microprocessor.