AttachInterrupt - fail to initiate inside a class
Firstly, if detection_door is a non-static member function, then C++ simply has no such expression syntax as just detection_door. Such functions have to either be called (with () operator) or be taken address of (with &amp; operator). You can't just say detection_door. That's meaningless, which is what the compiler is telling you.

Secondly, as you already realized, regardless of the syntax a non-static class member function cannot be used as an interrupt handler. You need a freestanding ("ordinary") function as a handler or a static class member. Non-static class methods are beasts of completely different and incompatible nature.

I see that you have multiple ledDoor objects that you want to attach to interrupts independently.

At the level of attachInterrupt and void (void) handlers you will not be able to use a single interrupt handler function and then properly dispatch the handling to multiple individual objects. The high-level attachInterrupt mechanism is insufficient to work around this limitation in a proper way. (At ISR level you can do that, the same way Servo.h handles multiple servos, but it is more complicated.)

For this reason, in your case, as long as you want to stay at attachInterrupt level, it is better to just implement two separate interrupt handlers as external functions that will call your class methods for your existing global objects

ledDoor door1(sensorPin_1, relayPin1);
ledDoor door2(sensorPin_2, relayPin2);

void handler_door1()
{
  door1.detection_door();
}

void handler_door2()
{
  door2.detection_door();
}


and then just attach these handlers to your desired pins in a regular way.

static in this case can only change things in a purely cosmetic way.



On the second thought one can wrap the above into a quasi-elegant implementation that might look as follows

constexpr unsigned N_PINS = 16; // Range of attachable pin numbers

class ledDoor 
{
  // ...

  static ledDoor *self[N_PINS];
  static void (*const HANDLERS[N_PINS])();

  template &lt;unsigned PIN&gt; static void handler() 
  { // This is the actual interrupt handler that will dispatch the call to
    // the `detection_door` method of the proper class object
    self[PIN]-&gt;detection_door();
  }

  // ...

  void attach()
  {
    self[_sensorPin] = this;
    attachInterrupt(digitalPinToInterrupt(_sensorPin), HANDLERS[_sensorPin], CHANGE);
  }

  void detection_door()
  {
    // Your code
  }
};


And somewhere in one of the .cpp files

// Definitions and initializers for static members

ledDoor *ledDoor::self[N_PINS] = {};

void (*const ledDoor::HANDLERS[N_PINS])() = 
{
  ledDoor::handler&lt;0&gt;,
  ledDoor::handler&lt;1&gt;,
  // ...and so on...
  ledDoor::handler&lt;15&gt;
};


This uses a dedicated callback for each pin. Maybe a better idea would be to use interrupt number (i.e. the result of digitalPinToInterrupt) for indexing instead of pin number.

The same thing can be rewritten through lambdas instead of a template. I.e. one can get rid of ledDoor::handler&lt;&gt; template and instead initialize the HANDLERS array as 

void (*const ledDoor::HANDLERS[N_PINS])() = 
{
  [](){ ledDoor::self[0]-&gt;detection_door(); },
  [](){ ledDoor::self[1]-&gt;detection_door(); },
  // ...and so on...
  [](){ ledDoor::self[15]-&gt;detection_door(); }
};


Note that this approach is a bit more memory wasteful that it could have been, since it uses a number of static tables of pre-determined size. In essense this is a slightly different implementation of the same "gluing" approach as described here.