现有类设计中的问题实现功能

时间:2010-10-09 21:30:15

标签: c++ class-design

我目前开始参加我的编程课程的学期项目 - 编程全自动驾驶模拟器。所有汽车都通过AI操纵,地图打印在控制台中。

第一张表要我们创建几个基本类:FCCompact(汽车),扫描仪(AI),ID(地形)和世界(地图)。

扫描仪目前在我的FCCompact类中实现为“HAS-A”,如下所示:

// FCCompact.h
class FCCompact
{
private:
    struct fImpl;
    fImpl *fImpl_;
/* ... */

// FCCompact.cpp
struct fImpl
{
    Scanner scanner_;
    /* ... */
};

有问题的扫描仪功能是

const ID& scanForID( int fovNumber,            // How far it can see
                     FCCompact::Direction dir, // Direction car is facing
                     const Location& loc);     // Location of car

到目前为止一切顺利。但是,整个地图位于World类中的容器vector< deque<ID> >(1)中;我不确定如何访问它。

到目前为止发布的功能已由老师提供给我们,因此它们应该能够使用给定的参数来实现。我不知道该怎么做。

我的第一个想法是打电话给World::getID(Location &),但这不是静态的。使它静止后,它就不能再访问非静态成员了(呃,我忘记了)。我还做了一个调用非静态函数的静态函数;同样的问题(双duh)。

然后我抛弃了老师的指导原则并简单地传递了整个World对象,但这也没有真正起作用。

我该怎么办?

请记住,这是技术上的功课,我不想要完整,合格的答案,甚至可以让我完全实现我想做的事情。我想尽可能多地从这个项目中学习,所以请指出我正确的方向。

(1):容器类型的奇怪选择?我想如果在控制台上打印世界,使用向量快速访问每一行将是有益的,因为不会插入或删除队列,访问时间也很棒。

另一方面,deque很容易用于访问范围,这是有利的,因为我会经常更改相邻列(沿x轴或y轴行驶的汽车)。这种选择没有迅速实现;我仍然在这个,一个列表或一个简单的向量之间徘徊。

世界级

class ID;
class World
{
    typedef std::pair<int, int> Location;

private:    
// vector<deque<ID> > map
// int mapHeight, mapWidth
// string mapName
    struct wImpl;
    wImpl *pimpl_;

public:
    World();
    ~World();

    void create(const std::string& name = "FC-City");

    int getHeight() const;
    int getWidth() const;

    ID getID(const Location& loc);

    friend std::ostream& operator<<(std::ostream& os, World& world)
    {
        return os;
    }

private:
    void loadMap(std::string name = "FC-City");

private:
    World(const World& other);
    World& operator=(const World& other);
};

班级扫描仪

class ID;
class Scanner
{
    typedef std::pair<int, int> Location;

public:
    Scanner();
    ~Scanner();

    const ID& scanForID( int fovNumber, 
                         FCCompact::Direction dir, 
                         const Location& loc);

private:
    Scanner(const Scanner& other);
    Scanner& operator==(const Scanner& other);
};

class FCCompact

class ID;
class FCCompact
{
    typedef std::pair<int, int> Location;

public:
    enum Direction
    {
        N, E, S, W, 
        NA = -1
    };

private:
// Scanner scanner
// Location loc
// Direction dir
// ID id
    struct    FCCImpl;
    FCCImpl  *pimpl_;

public:
    FCCompact( const ID& id,
               const Location& loc,
               const Direction& dir);

    FCCompact( const char ch,
               const Location& loc,
               const Direction& dir);

    const ID& getID()  const;
    Location  getLoc() const;
    Direction getDir() const;
    void      setDir( Direction& dir );

    void step();
    void hide();
    void show();
};

班级ID

class ID
{
public:
    enum Trait
    {
        Traversable,
        NotTraversable,
        Mobile,
        Undef
    };

private:
    Trait trait_;
    char appearance_;

public:
    ID( char outputChar, Trait trait )
        : appearance_(outputChar), trait_(trait)
    { }

    ID( char outputChar )
        : appearance_(outputChar), trait_(Trait::Undef)
    { }

    char getToken()  const { return appearance_; }
    Trait getTrait() const { return trait_; }

    void setTrait(Trait trait) { trait_ = trait; }
};

2 个答案:

答案 0 :(得分:1)

听起来你想要类World的单例模式。

class World {
public:
  static World* getWorld();

private:
  static World* _singleton;
};

您可以从构造函数和/或_singleton初始化create()。如果您愿意,getWorld()可以返回引用(或在失败时抛出异常)。由您来思考:如果有人尝试创建多个世界会怎么样?你应该在程序结束时清理World::_singleton吗?

答案 1 :(得分:1)

Scanner应该有一个接受World引用的构造函数;存储一个指向该参数的指针,以便稍后当你需要一个拥有一个世界的世界时。

请勿使用单身they're stupid。你可以使用全局,但这里确实没有必要。 Scanner需要World进行操作,因此您需要使用World进行操作,以便进行操作:

struct bar;

struct foo
{
    // foo cannot operate without a bar,
    // therefore it needs to be supplied with
    // one to be able to construct
    foo(const bar& pBar) :
    mBar(&pBar)
    {}

    void i_need_bar()
    {
        mBar->use_bar();
    }

    bar* mBar;
};