繁体   English   中英

如何设计一个始终是另一个 class 成员的 Class

[英]How to design a Class that will always be a member of another class

想象一下,我有一个fishTank 这个 class 将代表一个鱼缸,它有一个大小,一些鱼可以进入的边界,一些鱼不能进入的障碍物,一些水流过鱼缸,让鱼四处走动,等等。

class fishTank
{
private:
    double length;
    double height;
//And some more complex things that define a fish tank
public:
     fishtank(double, double, ...);
}

现在我需要往鱼缸里加鱼。 声明我的鱼 class 的适当方式是什么? (鱼代表一大群个体鱼)

  1. 我的鱼总是在鱼缸里,我一个人fishTank是没有意义的。
  2. 鱼需要知道fishTank的属性,鱼 class 取决于鱼缸:鱼在鱼缸中的装载方式取决于鱼缸的大小,鱼的移动方式取决于陷阱的大小和属性, ETC。
  3. 同一个鱼缸里可以有很多不同种类的鱼。

我的第一次尝试是创建鱼 class 并将水箱作为参数传递给鱼构造函数。 然后将鱼的向量作为私有成员添加到水箱中:

class fish
{
private:
    //All properties of fish
public:
    fish(const fishTank& aTank, All other properties of fish);
}


class fishTank
{
private:
    std::vector<fish> fishInTank;
    //Same as before
public:
    //Same as before;
}

这真的是实现我需要的正确方法吗? 我只是不认为这是一个好的设计,我需要鱼缸作为鱼的 arguments,然后将每条鱼自己添加到鱼缸中。 这有意义吗?

这是否是实现抽象鱼 class 或在水箱内筑巢鱼之类的正确位置?

老实说,就像吃里斯一样,没有正确或正确的方法可以做到这一点。 我个人? 鱼缸会有一个鱼的向量,然后如果鱼需要游泳 1 个刻度,我会在鱼缸上有一个游泳方法。 这将调用每条鱼并告诉它们游泳,将鱼缸作为参数传递给它们的游泳方法。 像这样:

class FishTank;

class Fish {
    public:
        void swim(const FishTank* tank) {

        }
};

class FishTank {
    private:
        std::vector<Fish> allFish;

    public:
        void tick() {
            for(Fish& fish : allFish){
                fish.swim(this);
            }
        }
};

关于这个,go 真的有十几种方法。 我推荐阅读这样一本书: Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides (ISBN 10: 0201633612)

鱼需要知道fishTank的属性

那么你可以考虑让fish成为fishTankfriend

class fishTank
{
private:
    friend fish;
    std::vector<fish> fishInTank;
...

现在任何fish实例都可以访问任何给定fishTank实例的所有private成员。

您的Fish class 可以在FishTank class 中声明,甚至是受保护的或私有的。 这将使在Fish之外使用变得更加困难/不可能。 但是没有办法规定它只能是FishTank的直接成员。

class FishTank {
private:
    class Fish {
        Fish(const Fishtank &parent);
        …
    };
    std::vector<Fish> fishInTank;

当在内部声明 class 时,它自动成为FishTank的朋友,可以访问坦克的所有成员,包括私人成员。

正如 Paul Evans 所指出的,您还可以使用friend指定来实现后一种效果。 如果Fish是一个复杂的 class 会很有帮助,这会使FishTank class 声明变得混乱,最好将其保存在另一个 header 文件中。 如果您的FishTank曾经将Fish暴露在外面,至少需要将鱼公开; 对于与Fish打交道的任何一方来说,包含完整FishTank header 也可能是一种负担。

您还可以使用命名空间来解释语义分组:

namespace fish_tank {
    class Fish { … };
    class Tank { … };
};

这是我的方式:

class FishTank;
class Fish
{
protected:
    FishTank* tank;
    Fish(FishTank* t) { tank = t; };
public:
    void swim();

    friend class FishTank;
};

class FishTank
{
private:
    std::vector<Fish*> allFish;
public:
    Fish* AddFish() {
        Fish* f = new Fish(this);
        allFish.push_back(f);
        return f;
    }
    void tick() {
        for (Fish* fish : allFish) {
            fish->swim();
        }
    }
    friend class Fish;
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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