简体   繁体   中英

Encapsulation in a Composition Class C++

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).

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 .

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.

实际上,使用friend会降低封装的程度,因为您的地图类会看到MapEntities所有MapEntities ,而不仅是tick方法。

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM