从行为中的函数访问参数 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 Runner
的 MoveBehaviour* 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();
}
我正在创建一个程序来模拟不同跑步者之间的比赛,使用行为 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 Runner
的 MoveBehaviour* 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();
}