Search code examples
c++inheritanceabstract-classvirtual-inheritance

C++ abstract base class constructors/destructors - general correctness


I would like to have a C++ Interface that must be overridden (if this is possible) when inherited. So far, I have the following:

class ICommand{

public:
    //  Virtual constructor. Needs to take a name as parameter
    //virtual ICommand(char*) =0;
    //  Virtual destructor, prevents memory leaks by forcing clean up on derived classes?
    //virtual ~ICommand() =0; 
    virtual void CallMe() =0;
    virtual void CallMe2() =0;
};

class MyCommand : public ICommand
{
public:
    // Is this correct?
    MyCommand(char* Name) { /* do stuff */ }
    virtual void CallMe() {}
    virtual void CallMe2() {}
};

I have purposely left how I think the constructor/destructor's should be implemented in ICommand. I know if I remove the comments, it will not compile. Please could someone:

  1. Show me how to declare the constructor/destructor's in ICommand and how they are meant to be used in MyCommand
  2. Have I set things up correctly in ICommand so that MyCommand must override CallMe and CallMe2.

Solution

  • C++ does not allow for virtual constructors. A simple implementation (without the virtual constructor) would look something like this:

    class ICommand {
    public:
        virtual ~ICommand() = 0;
        virtual void callMe() = 0;
        virtual void callMe2() = 0;
    };
    
    ICommand::~ICommand() { } // all destructors must exist
    

    Note that even a pure virtual destructor must be defined.

    A concrete implementation would look exactly like your example:

    class MyCommand : public ICommand {
    public:
        virtual void callMe() { }
        virtual void callMe2() { }
    };
    

    You have a couple of options for the constructor. One option is to disable the default constructor for ICommand, so that subclasses will have to implement a constructor that calls your ICommand constructor:

    #include <string>
    
    class ICommand {
    private:
        const std::string name;
        ICommand();
    public:
        ICommand(const std::string& name) : name(name) { }
        virtual ~ICommand() = 0;
        virtual void callMe() = 0;
        virtual void callMe2() = 0;
    };
    
    ICommand::~ICommand() { } // all destructors must exist
    

    A concrete implementation would now look something like this:

    class MyCommand : public ICommand {
    public:
        MyCommand(const std::string& name) : ICommand(name) { }
        virtual void callMe() { }
        virtual void callMe2() { }
    };