This is similar to other questions I'm sure, I read through. I am trying to write a move class. I need a Player class and an Item class that inherits the move class, or vice versa. That is what I am having difficulty with. I can't wrap my head around, or get to work, a way that the base class is not "Move." I'm lost here...
class Player {
protected:
int x;
int y;
int str;
int speed;
int level;
int exp;
public:
Player(int _str, int _speed, int _level, int _exp) { x=0;y=0;str=_str;speed=_speed;level=_level;exp=_exp; }
int GetX() {return x;}
int GetY() {return y;}
int GetStr() {return str;}
int GetSpeed() {return speed;}
int GetLevel() {return level;}
int GetExp() {return exp;}
};
class Move : public Player {
public:
void TryMove(int n) { x += n; }
};
int main(int argc, char *argv[])
{
Player You(101, 5, 3, 43625);
//You.TryMove(5); how?
}
TryMove(5) fails. If I do it the other way, then they type is then Move (?) and that doesn't sound right at all...
The way that I would recommend thinking of it is the Is A or Has A idiom. So... Is the Player a Move? Probably not, Is the Move A Player? also probably not. Then lets try the Has A. Does The Move Have a Player or Does the Player Have A move? I would Say that the Player Has a Move Personally. This would mean not using inheritance but rather having the player contain an instance of the Move class. So...
class Player{
public:
Move myMove;//where move is defined already as whatever you need it to be.
};
//then your main
int main(int argc, const char** argv){
//...other setup here
Player p;
p.myMove.TryMove(10);
//whatever else...
}
This is how i might approach your design. As far as the error... In the code above you had Move inherit from Player but you created a Player and expected it to have the functionality of Move but it would have no way of having that functionality based on the inheritance you set up in the example code.
Let me know if you need any clarification of what I have said or anything else. Good Luck
EDIT:
Based on your comment I would suggest that you use a wrapper function that will get the value that you need.
class Player{
public:
void TryMove(int i);
private:
Move myMove;
int x;//the value you will be getting from Move::tryMove
};
void Player::TryMove(int i){
this->x = myMove.tryMove(i);//store the value of the function call
//the function obviously won't be a void function in this case
}
There are other ways you could do this but this way is simple. If you are set on using inheritance to solve your problem I would have Player inherit from Move, But I still stand by my original answer I just wanted to help explain further.
First of all, public inheritance means IS-A relationship. So Move IS-A Player does not make any sense. Your design is wrong.
About your error, this is just silly. You are creating a Player object You and calling method of Move on it. To use methods of class Move, you have to create object of Move(or any publicly derived class).
class Move : public Player {
public:
//either create a ctor that will pass params to parent ctor, or create an empty ctro in parent class
Move(int _str, int _speed, int _level, int _exp):Player(_str,_speed,_level,_exp){}
void TryMove(int n) { x += n; }
};
int main(int argc, char *argv[]){
Move You(101, 5, 3, 43625);
You.TryMove(5);
}
I would design it as following:
class Movable{
public:
virtual bool TryMove()=0;
};
class Player: public Movable {
public:
bool TryMove() override{
//implementation code
}
//other members
};
int main(){
Movable* player = new Player(101, 5, 3, 43625);
player->TryMove();
delete player;
}
Related
I am new to C++ and I am creating a small program to understand more about inheritance in programming languages.
From what I gather, inheritance is when you have the authority and permission to obtain all member functions and values of the parent/base class. An analogy in real life would be inheriting some of my father's physical properties like eye colour etc (although I wish I could inherit his business mind...)
Anyways, one thing I am trying to do is to try and pass an already initialized object into an inherited class constructor.
This is my code so far:
#include <string>
#include <iostream>
using namespace std;
class player{
private:
string name;
int level;
public:
player(const string &n, const int &l) : name(n), level(l){};
string getName() const {return name;}
int getLevel() const {return level;}
};
class score: public player{
private:
int scores;
public:
score(const int &s, const string &n, const int &l) : player(n, l), scores(s){};
void setScore(int newScores){scores = newScores;}
int getScore() const {return scores;}
};
int main(){
player steve("steve", 69);
cout << steve.getName() << endl;
cout << steve.getLevel() << endl;
}
Basically, I want to pass the object that I have intialised in my main() program function steve by reference into a constructor in the score class. However, I don't know how to do this? Would it be something like score(const player &p, const int &s) : player(&p), scores(s)?? I get how to pass like member values, but I am interested in passing in objects themselves?
Would mean a lot if someone could assist me here, as I really like programming especially C++
You can't extend an object of a base class (player) to an object of a child class (score) because this would require to allocate more memory space directly after the original object to store the additional elements of the child class.
In your example, you can define this constructor to copy values from the player object for a new score object:
score(const player &p, const int &s) : player(p.n, p.l), scores(s){};
If you just want to link the player object, then the score class must include a pointer to this object.
say you have a class coded like this:
class Monster
{
public:
Monster(std::string& name, int hp, int acc, int xpReward
int armor, const std::string& weaponName,
int Lowdamage, int highdamage);
//insert methods
private:
//data types
};
what is the Monster(.... line do, create objects for the monster class? Is this a constructor? Really want to know everything this thing does
It's the declaration of a parameterized constructor. Right now, it's just the declaration, it does nothing, you did not post the code that belongs to it.
Should you use accessors on complex data types? Here is an example:
Say I've got a Player class and inside it theres a Sprite object. Let's say the Sprite object has a setPosition() accessor method. Now let's say I want to call that method through the player, so I create an accessor to the Sprite object in the Player.
class Player
{
public:
const Sprite& getSprite() const;
private:
Sprite sprite;
}
Now let's say I create a 'Player' object, how do I call setPosition on the sprite? I can't just say playerObject.getSprite().setPosition(); because the Sprite reference the getSprite() method returns is const.
Should I just make the sprite object public in this situation considering the sprite object has protection against all it's members? Or is that a bad practice and I do need to use accessors?
There is no good answer:
Having a 2D point:
class Point {
public:
// Skipping constructors here.
int x() const { return m_x; }
int x&() { return m_x; }
int y() const { return m_y; }
int y&() { return m_y; }
private:
int m_x;
int m_y;
};
looks like an overkill compared to
struct Point {
int x;
int y;
};
The first allows you to change the internal data (lets say) to a std::vector and the second data structure allows no changes. Even the first is cumbersome, I prefer that (but it is a matter of taste)
playersystem and rocketsystem inherit from system, playersystem contains pointer to rocketsystem. im getting an error when i try to access anything that is in system that rocketsystem is supposed to inherit. the runtime error is "expression cannot be evaluated" i set a breakpoint in visual studio, hovered the mouse over the position vector and it said that.
edit: for posterity this is what i was doing, and it turns out it is working, i was just setting th rocketsystem pointer to null for some reason
class Vector2D
{
public:
float x;
float y;
Vector2D(float x_, float y_) :x(x_),y(y_){}
};
class System
{
protected:
vector<Vector2D> position;
public:
void addEntity(Vector2D newPos)
{
position.push_back(newPos);
}
};
class projectile :public System
{
public:
void createRocket(Vector2D pos)
{
addEntity(pos);
}
};
class player : public System
{
public:
projectile* rocketSystem;
void init(projectile* rocketsys){rocketSystem = rocketsys;}
void fireRocket(Vector2D pos)
{
rocketSystem->createRocket(pos);
}
};
int main (int argc, char * const argv[])
{
player* PlayerSystem = new player;
projectile* RocketSystem = new projectile;
PlayerSystem->init(RocketSystem);
PlayerSystem->fireRocket(Vector2D(0,0));
return 0;
}
I'm going to use my psychic powers and guess that the System class doesn't have a createRocket() member. Since playersystem has a System *rocketSystem and not a rocketsystem *rocketSystem, the only functions that can be invoked on the rocketSystem member are those declared in the System class. It has to be a rocketsystem* if you want to be able to call that function, and the rocketsystem class has to be declared before the playersystem::fireRocket function is defined.
I need a way for a single variable to represent two kinds of objects derived from the same base class.
It's kinda hard to describe but I'll try the best:
Say the base class:
class Rectangle
{
float w;
float h;
const float area() {return w*h;}
};
And the two derived classes:
class Poker : Rectangle
{
int style; // Diamond, Club, ....
int point; // A~10, J, Q, K
};
class BusinessCard : Rectangle
{
string name;
string address;
string phone;
};
Now is it possible to declare an object, which could be either a poker or a business-card?
'cuz the usage below is illegal:
Rectangle* rec;
rec = new Poker();
delete rec;
rec = new BusinessCard();
Polymorphism might be a way but since it's only good for changing base-class' member attributes, I need this object to be able to represent exactly either of the derived objects.
EDIT:
Thanks for the all the answers. The public inheritance , the virtual destructor and even the boost::variant typedef are all fantastic hints.
You can do that. The problem is the inheritance modifier for classes is private. Most of the time, private inheritance is not what you want to use. Instead, declare it explicitly as public:
class Rectangle
{
float w;
float h;
const float area() {return w*h; }; // you missed a semicolon here, btw
virtual ~Rectangle() { } // to make `delete` work correctly
};
class Poker : public Rectangle // note the public keyword
{
int style; // Diamond, Club, ....
int point; // A~10, J, Q, K
};
class BusinessCard : public Rectangle
{
string name;
string address;
string phone;
};
Then your code snippet should work.
You need to change the qualifier for the inheritence to public.
class Poker : public Rectangle
{
int style; // Diamond, Club, ....
int point; // A~10, J, Q, K
};
class BusinessCard : public Rectangle
{
string name;
string address;
string phone;
};
is what you want. Now both classes, BusinessCard and Poker are of type Rectangle.
I need this object to be able to
represent exactly either of the
derived objects.
Don't know if I understand it correct but have a look at boost::variant
typedef boost::variant<Poker, BusinessCard> PokerOrBusinessCard
Now you can access the derived classes with a boost variant visitor class.
Maybe this can be a solution.
I think what you may be looking for is multiple inheritance, where an object can sometimes be a Poker and sometimes a BusinessCard.
See here for a tutorial:
http://www.deitel.com/articles/cplusplus_tutorials/20060225/MultipleInheritance/index.html
Note that you can decide to make it one or the other if you wish, it does not have to be both all of the time, which may satisfy what you need.
Change the subclasses to use public derivation and your code works, with some cleanup. You should also use virtual destructors so the delete works correctly.
class Rectangle
{
float w;
float h;
const float area()
{
return w*h;
}
public:
virtual ~Rectangle(){};
};
class Poker : public Rectangle
{
int style; // Diamond, Club, .... int point; // A~10, J, Q, K
};
class BusinessCard : public Rectangle
{
string name;
string address;
string phone;
};