mercredi 3 janvier 2018

Alternate to virtual function call on base destructor

So, I've written the following code.

#include <iostream>

class AbstractMachine
{
public:
    void powerOn();
    void powerOff();
    bool isPoweredOn();

    virtual ~AbstractMachine();

protected:
    virtual void powerOnImpl() = 0;
    virtual void powerOffImpl() = 0;

private:
    bool m_isPoweredOn;
};

bool AbstractMachine::isPoweredOn()
{
    return m_isPoweredOn;
}

void AbstractMachine::powerOn()
{
    if (!m_isPoweredOn)
    {
        powerOnImpl();
        m_isPoweredOn = true;
    }
}

void AbstractMachine::powerOff()
{
    if (m_isPoweredOn)
    {
        powerOffImpl();
        m_isPoweredOn = false;
    }
}

AbstractMachine::~AbstractMachine()
{
    powerOff();       // (1)
    std::cout << "Destroying a machine" << std::endl;
}

class AirConditioner : public AbstractMachine
{
protected:
    void powerOnImpl() override;
    void powerOffImpl() override;
public:
    ~AirConditioner();
};

void AirConditioner::powerOnImpl()
{
    std::cout << "Turning on air conditioner" << std::endl;
}

void AirConditioner::powerOffImpl()
{
    std::cout << "Turning off air conditioner" << std::endl;
}

AirConditioner::~AirConditioner()
{
    //powerOff();        // (2)
    std::cout << "Destroing air conditioner" << std::endl;
}


int main()
{
    AbstractMachine *machine = new AirConditioner();
    machine->powerOn();
    delete machine;
}

This is going to fail, because derived object is already destroyed when the base destructor calls derived function on (1).

This runs fine when I comment (1) and uncomment (2), but what I want to do here is to automatically and always turn off the machine before it gets destroyed, though the 'power off' action depends on the custom machine.

Is there a better way of doing this? Should I just give up? Or is it not even the right way of a design on OOP?

Aucun commentaire:

Enregistrer un commentaire