从行为中的函数访问参数 class - 多态性

Access parameter from function in behaviour class - polymorphism

我正在创建一个程序来模拟不同跑步者之间的比赛,使用行为 classes 来实现不同类型的跑步者动作。

为此,将实现一个抽象的 MoveBehaviour class,以及其他几个具体的子 classes(WalkBehaviour、SleepBehaviour、SlideBehaviour 等)。

抽象的 MoveBehaviour class 将需要一个纯虚拟的 move() 函数,适当的行为将在具体的子 class 中实现。此 move() 函数计算跑步者的新位置 newPos,给定其当前位置 oldPos,并且 move() 函数将 return 日志参数中移动的简短文本描述(等等。“向前走1 step") ,它将在后面的步骤中打印到屏幕上。我觉得好像我没有正确地 return 在这些函数中输入我的日志值,这涉及到另一个问题。

在 Runner.cc 的 update() 函数中,我应该随机 select 跑步者的下一步行动。这涉及 40% 的新步行行为、40% 的睡眠行为和 20% 的滑行行为。我应该使用新的行为对象来计算将存储在 newPos 参数中的新位置,然后我 将移动记录在跑步者的当前日志数据成员 中。以此类推,如果跑步者名为 Timmy,并且新的移动行为是行走,则当前日志数据成员将存储字符串“Timmy walked a step”。

回到我的日志,我不确定如何访问我在每个移动函数中为每个行为声明的字符串 class。我注意到 Runner.cc 中有一个 getLog() 函数,但我觉得使用它没有意义。这让我觉得我不应该在移动 classes 中声明“走了一步”字符串等,而是在更新 classes 中声明。

此外,我不明白如何让新的行为对象计算将存储在 newPos 参数中的新位置,我也希望得到一些帮助。

为了获取日志值,我只是在下面打印跑步者的名字,我的尝试是将日志值中的任何内容附加到这句话,但我不确定如何访问日志值。

如果需要,我可以包含 SleepBehaviour 和 SlideBehaviour classes,但它们实际上与 WalkBehaviour 相同,我认为只需要一个示例。

Runner.cc

void Runner::update(Position& newPos){
    int r;
    r = random(100) + 1;
    if(r <= 40){ 
        WalkBehaviour* walk = new WalkBehaviour;
    }else if (r <= 40){
        SleepBehaviour sleep = new SleepBehaviour;
    }else{
        SlideBehaviour* slide = new SlideBehaviour;
    }
    cout << name << endl;
    
}

Position.cc

#include <iostream>
using namespace std;
#include <string>
#include "Position.h"

Position::Position(int i1, int i2) : row(i1), column(i2){ 
}
Position::getRow(){ return row; }
Position::getColumn(){ return column; }
void Position::setRow(int r){ row = r; }
void Position::setColumn(int c){ column = c; }

MoveBehaviour.h

#ifndef MOVEBEHAVIOUR_H
#define MOVEBEHAVIOUR_H

#include <iostream>
#include "Position.h"
using namespace std;

class MoveBehaviour
{
  public:
    virtual void move(Position&, Position&, string&) = 0;
    virtual ~MoveBehaviour() = default;
};

class WalkBehaviour : public MoveBehaviour{
  public:
    virtual void move(Position&, Position&, string&);
    virtual ~WalkBehaviour();
};

class SleepBehaviour : public MoveBehaviour{
  public:
    virtual void move(Position&, Position&, string&);
    virtual ~SleepBehaviour();
};

class SlideBehaviour : public MoveBehaviour{
  public:
    virtual void move(Position&, Position&, string&);
    virtual ~SlideBehaviour();
};

WalkBehaviour.cc

#include <iostream>
using namespace std;
#include <string>
#include "MoveBehaviour.h"

void WalkBehaviour::move(Position& oldPos, Position& newPos, string& log) { 
    newPos.setColumn(oldPos.getColumn() + 1);
    newPos.setRow(oldPos.getRow());
    log = (" walked one step \n");
} 

WalkBehaviour::~WalkBehaviour(){}

这里:

if(r <= 40){ 
    WalkBehaviour* walk = new WalkBehaviour;
}else if (r <= 40){
    SleepBehaviour sleep = new SleepBehaviour;
}else{
    SlideBehaviour* slide = new SlideBehaviour;
}

您正在创建新行为并立即泄漏它们。您应该为它们分配 ti RunnerMoveBehaviour* behaviour;,首先删除其旧行为:

delete behaviour;
if(r <= 40){ 
    behaviour = new WalkBehaviour;
}else if (r <= 40){
    behaviour = new SleepBehaviour;
}else{
    behaviour = new SlideBehaviour;
}

您的 WalkBehaviour::move() 正确使用了 log(除了您不需要将文本字面量包含在 ()

首先,您需要实际使用多态性,方法是声明一个指向基础 MoveBehaviour 对象的指针,您让该指针指向派生实例。 此外,您需要确保不会泄漏内存,所以我选择了 std::unique_ptr,它会在函数退出时自动释放。

接下来,您可以简单地为将日志分配给的函数传递一个空的 std::string,并使用 std::stringstream 构造一个带有名称和移动描述的行。然后将此字符串流的输出一次性添加到 log 成员。

void Runner::update(Position& newPos) {
    int r;
    r = random(100) + 1;
    std::unique_ptr<MoveBehaviour> movement;
    if(r <= 40) { 
        movement = make_unique<WalkBehaviour>();
    } else if (r <= 80) {
        movement = make_unique<SleepBehaviour>();
    } else {
        movement = make_unique<SlideBehaviour>();
    }

    std::string moveLog;
    movement->move(currPos, newPos, moveLog);
    currPos = newPos;
   
    std::stringstream ss;
    ss << name << " " << moveLog << std::endl;
    log += ss.str();
}