Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm writing a cheat for an offline game, and have a class called Player which is responsible for getting and setting values in another process. However, my design for this class is very poor because the use of the class Player looks very messy and ugly, very difficult to read, and maintain
// declare variables here to read
if (Player.getthis() && Player.getthat() && Player.getthat() ... and so on)
//do stuff
class Player {
...
public:
...
// either of these calls can fail, so I return TRUE on success and FALSE on failure
BOOL GetHealth(float& health);
BOOL SetHealth(float& health);
...
};
So my question is, what is a better way of doing this?
Also: I don't necessarily need to read every single value of Player in memory, only a few at a time. That is why I don't have a single method such as BOOL UpdatePlayer() which will read everything and update the player
Here is how I would do it:
class Player {
public:
class AccessException : public std::exception {
friend class Player;
public:
virtual const char *what() const noexcept {
return "Error getting property with key " + key;
}
private:
AccessException(const std::string &key)
: key(key)
{}
std::string key;
};
float GetHealth() {
if (is_error) {
throw AccessException("health");
}
return health;
}
float GetPosX() {
if (is_error) {
throw AccessException("posX");
}
return posX;
}
};
void do_stuff() {
try {
float health = player.GetHealth();
float posX = player.GetPosX();
// Use health and posX...
} catch (const AccessException &ex) {
std::cerr << ex.what() << std::endl;
}
}
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have a problem with my getters and setters in C++. I implemented a Queue, I also implememented a class Process. My queue saves processes. My class Process has two attributes: "Identifier" and "Time" and also has setters and getters. I set 80 as its Time. The problem then is that I want to modify the time to 50 and it doesn't change. I think that the problem is the Queue, but I don't know where. Heres is my fragment of code
Queue<Process> process;
Process x;
x.setIdentifier("Hi");
x.setTime(80);
process.enqueue(x);
process.getElementFront().setTime(50);
process.print();
Here is my Queue code:
class Queue{
private:
int size;
Node <L> *front;
public:
.
.
.
//front()
L getElementFront() const{
return this->front->getElement();
}
Here is my Node code:
class Node{
private:
L elem;
Node *next;
public:
.
.
.
L getElement() {
return this->elem;
}
This is my Process Class:
class Process{
private:
string identifier;
int time;
public:
Process(){
identifier = "";
time = 0;
}
string getIdentifier(){
return identifier;
}
int getTime(){
return time;
}
void setTime(int time){
this->time = time;
}
void setIdentifier(string identifier){
this->identifier = identifier;
}
friend ostream &operator<<(ostream &o, const Process &p);
};
ostream &operator<<(ostream &o, const Process &p){
o<<"Identifier: "<<p.identifier<<"\n";
o<<"Time:"<<p.time<<"\n";
return o;
}
The output of the first code is: Time = 80. I should be Time = 50, but time wasn't modified.
I believe your function "getElementFront" returns a copy of your element, So your queue will never be affected. You can write a function like "setElementFront(int)" to affect the element directly or something like this.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
As the title says when I run my program, visual studio, give me that error. The class that produce that error is the following:
class UsesScene {
BaseScene & scene;
public:
UsesScene(BaseScene& scene) : scene(scene) {}
void Start() { scene.Start(); }
void EventHandler(SDL_Event ev) { scene.EventHandler(ev); }
void Update() { scene.Update(); }
void Draw(SDL_Renderer* renderer) { scene.Draw(renderer); }
};
The popup appears after } at the end of the initialization of the Start void.
Another code that can interact with these classes is the following:
void GameManager::regScene(UsesScene scene) {
if (display != NULL) {
UsesScene* ptr = &scene;
UsesScene** pptr = &ptr;
display = *pptr;
}
else
{
UsesScene* ptr = &scene;
UsesScene** pptr = &ptr;
buffer = *pptr;
}
}
the display & buffer are declared as
class GameManager
{
private:
SDL_Window* window;
SDL_Renderer* renderer;
UsesScene* display;
UsesScene* buffer;
bool isRunning;
bool reStart;
};
and for access to the display or buffer's parameter I use the following syntax:
display->Start();
and the last thing that has to do with this class is this part of code:
TestScene tScene;
UsesScene testScene(tScene);
this->regScene(testScene);
Test Scene simply extends BaseScene:
class BaseScene
{
private:
bool sceneloop = false;
public:
virtual void Start() { std::cout << "BasceScene::Start()" << std::endl; };
virtual void EventHandler(SDL_Event event) {};
virtual void Update() {};
virtual void Draw(SDL_Renderer* renderer) {};
void _toggleLoopMode() { sceneloop = !sceneloop; }
bool _sceneloop() { return sceneloop; }
};
How I can solve this?
ps:
some code that doesn't interfere with the Display and Buffer wasn't reported, if you need: free to ask
So, after a few hours of coding, thanks to Remy Lebeau, I've finally resolved this issue.
First I've changed the regScene() method and now looks like this:
void GameManager::regScene(UsersScene *scene) {
if (SceneManager::_display == NULL)
_display = scene;
else
_buffer = scene;
}
And then I pass the scene like this:
TestScene tScene;
UsersScene testScene(tScene);
sManager->regScene(&testScene);
Thanks to all.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I have this class to store fixed known data. Each object should have its own unique id in such way that, when the user calls Belt belt(1), an object with the correct values of name, perimeter, nOfPoints is created. Is there any better way to define these other parameters without a switch-case? Should I design this in another way? What are the disadvantages of such implementation?
class Belt {
private:
int _id;
std::string _name;
int _perimeter;
int _nOfPoints;
public:
Belt(int id){
_id = id;
switch (id)
{
case 1:
_name = "NEO";
_perimeter = 100;
_nOfPoints = 10;
break;
case 2:
_name = "PED";
_perimeter = 200;
_nOfPoints = 12;
break;
case 3:
_name = "ADT";
_perimeter = 400;
_nOfPoints = 20;
break;
}
}
};
Is there any better way to define these other parameters without a switch-case?
You could use a private static map to hold your prototypes:
class Belt {
private:
static const std:map<int,Belt> prototypes;
int _id;
std::string _name;
int _perimeter;
int _nOfPoints;
Belt(int id, const std::string name, int perimeter, int nOfPoints)
: _id(id), _name(name), _perimeter(perimeter), _nOfPoints(nOfPoints) {}
public:
Belt(int id) {
_id = id;
_name = prototypes[_id]._name;
_perimeter= prototypes[_id]._perimeter;
_nOfPoints= prototypes[_id]._nOfPoints;
// Or simpler instead of the lines above:
// *this = prototypes[id];
}
};
const std:map<int,Belt> Belt::prototypes = {
{ 1 , Belt(1,"NEO",100,10) }
, { 2 , Belt(2,"PED",200,12) }
, { 3 , Belt(3,"ADT",400,20) }
};
Also you might be interested to have a look at the Prototype Design Pattern. That's an alternative technique you can use, and gives you better flexibility.
If you're only going to have a fixed set of values to deal with, I'd suggest making static const instances in Belt. This has the advantage of avoiding any lookup overhead, and dealing with invalid input (e.g., somebody passes INT_MAX to your constructor). For example:
class Belt {
private:
int _id;
std::string _name;
int _perimeter;
int _nOfPoints;
Belt(int id, name, perimeter, nOfPoints)
: _id{id}, _name{std::move(name)}
, _perimeter{perimeter}, _nOfPoints{nOfPoints} { }
public:
static const Belt neo(1, "NEO", 100, 10);
static const Belt ped(2, "PED", 200, 12);
// ...
};
A user can create a local Belt by copying one of the existing objects, and still perform any local manipulations that they need.
int main() {
auto myBelt = Belt::neo;
myBelt.some_member_function();
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Using the example below, I would like to call the function printTop() from my 'Bottom' object. It seems perhaps I could use a pointer to the parent object?
class Bottom {
public:
void printBottom(){std::cout << "print bottom";};
};
class Top {
public:
void printTop(){std::cout << "print top";};
private:
Bottom bottom;
};
Thanks.
If this is truly where your heart is at, it can be done (doesn't mean i'd advocate it):
class Top;
class Bottom {
public:
Bottom( const Top& topLevelObj ) : _topLevelObj(topLevelObj) { }
void printBottom() const {std::cout << "print bottom";};
void printTop() const;
private:
const Top& _topLevelObj;
};
class Top {
public:
Top() : _bottom(*this) {}
void printTop() const {std::cout << "print top";};
private:
Bottom _bottom;
};
void Bottom::printTop() const { _topLevelObj.printTop(); }
Firstly your code will not execute due to an error in your code, figure it out.
Secondly, you cannot call function printTop() from your Bottom object because you have no access to printTop() from the Bottom class.
You could maybe rewrite the code in this way:
class Top {
public:
void printTop(){ std::cout << "print top"; }
};
class Bottom {
public:
void printBottom(){ std::cout << "print bottom"; }
Top top;
};
int main()
{
Bottom B;
B.top.printTop();
return 0;
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
As a practice program after learning C++, I am developing a text-based game. I am using object-oriented programming style for handling the worlds/their objects. Here's the necessary information about their definitions:
class Object
{
private:
unsigned int id;
public:
unsigned int getID() const { return id; }
};
class TakeableObject: public Object
{
...
};
class EdibleObject: public TakeableObject
{
private:
float healthEffect;
float staminaEffect;
public:
float getHealthEffect() const { return healthEffect; }
float getStaminaEffect() const { return staminaEffect; }
};
class Player
{
private:
float health;
float stamina;
TakeableObject inventory[256];
public:
eat(const EdibleObject* o)
{
health += o->getHealthEffect();
stamina += o->getStaminaEffect();
}
eat(int id)
{
if (inventory[id] == NULL)
throw "No item with that ID!";
eat((EdibleObject) inventory[id]);
inventory[id] = NULL;
}
};
So my question is - in Player::eat(int), is there a way I can make sure the Object at Player::inventory[id] is an EdibleObject (perhaps through exception handling?)
User dynamic cast to check the object type at runtime.
Or you can use a virtual function with default definition in parent and can update it as per your requirement in derived classes.
Instead of eat((EdibleObject) inventory[id]); use the following
EdibleObject *temp = dynamic_cast<EdibleObject *>( &inventory[id] );
if(temp) { eat(*temp); }
else { /* Handling */ }
Your code suffers Object splicing, make sure to get rid of that first.