c++inheritanceparent-childsettermutators

C++ function in parent return child


I would like to have the mutators (setters) in my class to return this to allow for jQuery-like a.name("something").address("somethingelse"); I have a parent class (Entity) and several childclasses (Client, Agent etc.). The mutators for most things are inherited from the Entity class (like name or address), but they return an Entity object, so I can't call Client mutators on them.

In other words:

// name mutator
Entity& Entity::name( const string& name ) {
    // [...] checks
    _name = name;
    return *this;
}

// budgetRange mutator
Client& Client::budgetRange( const long int& range ) {
    // [...] checks
    _budgetRange = range;
    return *this;   
}

then when I call it:

Client a; a.name("UserName123").budgetRange(50);

The compiler (logically) says, that the Entity object has no budgetRange member (because name returns an Entity, not a Client).

My question now is: how could I implement something like this? I thought about overloading all the Entity functions in the childclasses but that wouldn't be nice and would be against the idea of inheritance :)

Thank you in advance for your ideas :D


Solution

  • You should use the CRTP.

    template<class Derived>
    class Entity
    {
        Derived* This() { return static_cast<Derived*>(this); }
    
    public:
        Derived& name(const string& name)
        {
            ...
            return *This();
        }
    };
    
    class Client : public Entity<Client>
    {
    public:
        Client& budgetRange(const long& range)
        {
            ...    
            return *this;   
        }
    };
    

    If you want to use virtual functions, you can also add abstract base class, like this:

    class AbstractEntity
    {
    public:
         virtual void foo() = 0;
    
         virtual ~AbstractEntity();
    };
    
    template<class Derived>
    class Entity : AbstractEntity
    {...};