0

I have a map class, which contains a vector containing MapEntitys. MapEntity is a class of which Factory, Farm and 3 other classes are inherited from.

These 5 classes both should be "ticked" every few seconds, at which point they will all do a function individual to each class, but only the map class should be able to "tick" them.

How would I support this type of encapsulation in C++? Friends? Should I just use public methods and not misuse the methods? (Although I would prefer proper encapsulation for good practice, even though this code will not be re-distributed).

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Ell
  • 4,238
  • 6
  • 34
  • 60

4 Answers4

2

Syntactically you could use any of that.

However, if MapEntities are to be "ticked" from outside, the tick method should be part of their public methods. Actually, it should be a virtual public method of the MapEntity class.

And yes, public methods are proper encapsulation. They tell the user of your class what it can do. In this case, the user is the Map class and it can tick MapEntities.

You should consider other solutions (friends, anonymous namespaces etc.) only if MapEntities are designed to be used only by Map.

fouronnes
  • 3,838
  • 23
  • 41
2

You could use friend, but I think it's better to not put any restriction on what can 'tick' your MapEntity classes.

It's generally considered bad practice to put artificial limitations in your code. Even though you only want your map class to be able to call this function right now, this might change in the future.

Collin Dauphinee
  • 13,664
  • 1
  • 40
  • 71
  • Thanks for this, I thought putting limits on code was the right thing to do :s – Ell Mar 05 '11 at 22:10
  • No, the reason for using encapsulation is protecting data, not putting limits on code. You normally use encapsulation when you want to protect data, usually to enforce side effects of the data changing. – Collin Dauphinee Mar 06 '11 at 00:03
0

Using friend would actually lower the degree of encapsulation, since your map class would see any privates of MapEntities, not only the tick method.

Doc Brown
  • 19,739
  • 7
  • 52
  • 88
0

In my opinion your task looks like design-pattern visitor description.

class Visitor;

class MapEntity
{
  public:
    virtual void tick(Visitor &v) = 0;
};

class Factory: public MapEntity
{
  public:
    void accept(Visitor &v);
    // ...
};

class Farm: public MapEntity
{
  public:
    void tick(Visitor &v);
    // ...
};

class Mill: public MapEntity
{
  public:
    void tick(Visitor &v);
    // ...
};

class Visitor
{
  public:
    virtual void visit(Factory *e) = 0;
    virtual void visit(Farm *e) = 0;
    virtual void visit(Mill *e) = 0;
};

void Factory::tick(Visitor &v) { v.visit(this); }
void Farm::tick(Visitor &v) { v.visit(this); }
void Mill::tick(Visitor &v) { v.visit(this); }

class SomeVisitor: public Visitor
{
    void visit(Factory *e) { /* ... */ };
    void visit(Farm *e) { /* ... */ };
    void visit(Mill *e) { /* ... */ };
};

class OtherVisitor: public Visitor  { /* ... */ };

client code:

MapEntity *enities[];
// ...
SomeVisitor v1;
OtherVisitor v2;
for (int i = 0; i < N; ++i)
{
  entities[i].tick(v1);
}
for (int i = 0; i < N; ++i)
{
  entities[i].tick(v2);
}
Oleg Svechkarenko
  • 2,508
  • 25
  • 30