C ++ function in parent reverse

Honestly, I really don't know how to ask this question, so please don't be angry :)

In any case, I want the mutators (setters) in my class to return thisto allow jQuery-like a.name("something").address("somethingelse"); . I have a parent class ( Entity) and several child classes ( Client, Agent etc.). Mutators for most things are inherited from a class Entity(for example, a name or address), but they return an object Entity, so I cannot 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 him:

Client a; a.name("Dorota Adamczyk").budgetRange(50);

The compiler (logically) says that the Entity object does not have a budgetRange member (since the name returns Entity, not the client).

: - ? Entity , :)

: D

+5
3

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;   
    }
};

, , :

class AbstractEntity
{
public:
     virtual void foo() = 0;

     virtual ~AbstractEntity();
};

template<class Derived>
class Entity : AbstractEntity
{...};
+7

" "; , , :

template <typename Derived>
struct Entity {
    Derived & name(std::string const & name) {
        // stuff
        return static_cast<Derived&>(*this);
    }
};

struct Client : Entity<Client> {
    Client & budget(long range) {
        // stuff
        return *this;
    }
};

Client().name("Mike").budget(50); // should compile

, Entity. , (.. ), Entity.

+3

, , , CRTP :

CRTP , Client, Derived Client. , CRTP-,

template<class Derived>
class Entity_T
{
protected:
    Derived* This() { return static_cast<Derived*>(this); }
public:
    Derived& name(const string& name)
    {
        ...
        return *This();
    }
};

template<class Derived>
class Client_T : public Entity_T<Derived>
{
    Derived& budgetRange(const long& range)
    {
        ...    
        return *This();   
    }
};

To provide the user without templates, Client_Tadd

class Client : public Client_T<Client> {};

Regardless of whether to increase the increased code base, you are completely dependent. Please note that I did not compile the code above.

+2
source

All Articles