Задача реализации функции с существующим дизайном класса - PullRequest
0 голосов
/ 10 октября 2010

В настоящее время я начал семестровый проект по программированию - программирование полностью автономного симулятора вождения. Все машины управляются через AI, и карта печатается в консоли.

На первом листе мы хотим создать пару базовых классов: FCCompact (Автомобиль), Сканер (AI), ID (ландшафт) и Мир (Карта).

Сканер в настоящее время реализован как «HAS-A» в моем классе FCCompact следующим образом:

// 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

Пока все хорошо. Однако вся карта находится в контейнере vector< deque<ID> > (1) в классе World; Я не уверен, как получить к нему доступ.

Функции, опубликованные до сих пор, были предоставлены нам учителем, поэтому они должны быть в состоянии быть реализованы с заданными параметрами. Я просто понятия не имею, как это сделать.

Моей первой идеей было позвонить World::getID(Location &), но это не статично После того, как он стал статическим, он больше не может получить доступ к нестатичным элементам (да, я забыл это). Я также сделал статическую функцию, которая вызывает нестатическую функцию; та же проблема (двойной дух).

Затем я бросил указания учителя и просто передал весь объект 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);
};

класс 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 ]

1 голос
/ 10 октября 2010

Scanner должен иметь конструктор, который принимает ссылку на World; сохраните указатель на этот аргумент, чтобы позже, когда вам нужен мир, он у вас есть.

Не используйте синглтон, они глупы . Вы можете использовать глобальный, но здесь действительно нет необходимости. Для 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;
};
1 голос
/ 10 октября 2010

Звучит так, будто вы хотите шаблон синглтона для класса World.

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

private:
  static World* _singleton;
};

Вы можете инициализировать _singleton из вашего конструктора и / или create(). getWorld() может вернуть ссылку (или выдать исключение при ошибке), если вы предпочитаете. Вам решать, что делать: если кто-то попытается создать несколько миров? Стоит ли убирать World::_singleton в конце программы?

...