Question

I was wondering how it is best to create a data entity in C++, where the "setter" is private and "getter" is public. i.e the creator of the entity should be able to set the data, but the user/consumer/client is only able to get the data.

Lets consider the entity EntityX:

class EntityX
{
  public:
    EntityX(int x, int y) : x(x), y(y)
    {}
    int GetX() const {return x;}
    int GetY() const {return y;}
  private:
    int x,y; // Effective C++ third edition, Item 22: Declare data members private
}

And a class method which creates the entity and returns it to the client:

const shared_ptr<EntityX> classz::GetEntityX()
{
  shared_ptr<EntityX> entity(new EntityX(1,2));

  return entity;
}

This in my mind makes the setter private and the getter public, but this example is not practical if the data members are > 5-10... How would you make a entity class/struct such that the setter is "private" and the "getter" is "public", without making the constructor taking in all the data member variables.

Thanks in advance

Was it helpful?

Solution

What about setting your Creator as friend to class EntityX:

   class EntityX
    {
      friend class Creator;
      public:
        EntityX(int x, int y) : x(x), y(y)
        {}
        int GetX() const {return x;}
        int GetY() const {return y;}
      private:
        int x,y; // Effective C++ third edition, Item 22: Declare data members private
    };

Update:

Or you could use templatized friend-ship, see code below:

#include <iostream>
#include <memory>

template<class T>
class EntityX
  {
  friend T;
  public:
    EntityX(int x, int y) : x(x), y(y) {}
    int GetX() const {return x;}
    int GetY() const {return y;}
  private:
    int x,y; // Effective C++ third edition, Item 22: Declare data members private
  };

struct Creator
  {
    static const std::shared_ptr<EntityX<Creator>> create() 
      {  
      std::shared_ptr<EntityX<Creator>> entity = std::make_shared<EntityX<Creator>>(1,2);
      entity->x = 1;
      entity->y = 2;
      return entity;
      }
  };

int main()
{
  std::shared_ptr<EntityX<Creator>> const E = Creator::create();
  std::cout << E->GetX() << ", " << E->GetY() << std::endl;

  return 0 ; 
}

OTHER TIPS

Your getter could return a const& so...

public:
int const& Getter();
private:
int const& Setter(int value);

with "setter" and "getter" are replaced with the name of the variable. so...

public:
int const& X();
private:
int const& X(int value);

you can also write the same thing with this syntax...

const int& X();

just a matter of how you want to write it.

Good luck, I hope i could help.

How about something like:

struct EntityValues
{
   Type1 value1_;
   Type2 value2_;
   (etc for all the members of Entity
};

class Entity
{
  public:
    Entity () : <set default values> 
    {
    }

    // this avoids the sea-of-parameters problem by bundling the data values
    // into a single parameter.  Data can be added to values by name in random order
    // before it is finally used here.
    Entity(const EntityValues & values) : <set members by pulling data from values>
    {

    }

    // individual public getters.
    Type1 getValue1()const { return value1_;}
    <repeat as necessary for other members>

    // get everything at once 
    // (an alternative to individual getters)
    // 
    void exportValues(EntityValues & values) const
    {
       <copy member to values>
    }

    // optional (this violates the "no public setters" constraint
    // but it does it in a controlled manner.
    void update(const EntityValues & values)
    {
       <set members by pulling data from values>
    }

private:
    <setters (if necessary) and members go here
 };

Also EntityValues could be a public, nested structure declared inside Entity (i.e. struct Entity::Values)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top