c++ polymorphism - accessing inhertied variables - c++

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.

Related

Base class undefined and fatal error C1903

I'm writing Monopoly game with C++ and SFML. My application already has around 20 classes and they work together pretty well but I can't find solution for one problem. First I need to show you a bit of my code, I'm sorry if I post too much code (Ill try to paste simple minimum), but problems happen all accross my application once I add 1 line of code - #include "GameEngine.h" into Field.h and I dont really know what. Let's start with heart of application, GameState class that has GameLoop inside
class GameState : public State {
sf::Clock m_clock;
sf::Sprite m_background;
GameEngine m_gameEngine;
public:
GameState();
void initialise();
void handleUserInput();
void update(sf::Time);
void draw();
};
GameState::GameState(std::shared_ptr<ApplicationData> data) : m_gameEngine(2, "John", "Richard") {
//2 players named John and Richard, just for tests now
}
Then class that handles all the logic, GameEngine
class GameEngine {
//players
std::vector<Player> m_players;
int m_numberOfPlayers;
int m_activePlayer = 0;
//game objects
GameBoard m_gameBoard;
public:
GameEngine(int, std::string, std::string);
GameBoard& getBoard() { return m_gameBoard; }
Player& getActivePlayer() { return m_players[m_activePlayer]; }
};
For now, it just creates two players
GameEngine::GameEngine(int numberOfPlayers, std::string playerOneName, std::string playerTwoName)
: m_numberOfPlayers(numberOfPlayers), m_firstDice(FIRST_DICE_POSITION_X, FIRST_DICE_POSITION_Y),
m_secondDice(SECOND_DICE_POSITION_X, SECOND_DICE_POSITION_Y) {
m_players.push_back(Player(playerOneName, sf::Color::Red, -5, 0));
m_players.push_back(Player(playerTwoName, sf::Color::Blue, -5, 0));
}
Player class is nothing special, few variables and getter and setter functions
class Player {
int m_positionID = 0;
std::string m_name;
sf::CircleShape m_token;
};
Another significant part is GameBoard
class GameBoard {
std::array<std::shared_ptr<Field>, BOARD_SIZE> m_board;
public:
GameBoard();
~GameBoard() = default;
std::shared_ptr<Field>& getField(size_t index) { return m_board[index]; }
};
And finnaly Field where all the problems start
class Field {
protected:
int m_positionID;
float m_positionX;
float m_positionY;
bool m_buyable;
public:
Field() {}
Field::Field(int positionId, float positionX, float positionY, bool buyable) :
m_positionID(positionId), m_positionX(positionX), m_positionY(positionY), m_buyable(buyable) { }
virtual ~Field() = default;
virtual void calculateCharge(GameEngine&) = 0;
};
Field is base class for all my fields in game like Property, Start, GoToJail, etc. I want something like that: player rolls the dice, he is moved to new position, this position is checked (inside GameEngine)
m_board.getField(m_gameEngine.getActivePlayer().getPositionID())->calculateCharge();
Now calculateCharge() will perform a bit different action for every class, simple runtime polymorphism, but I want this function to actually call some functions from inside GameEngine, thats why I want to pass GameEngine& into this function, but once I '#include GameEngine.h' into 'Field.h', I got
error C2504: 'Field': base class undefined
followed by several errors from derived classes, that they cannot access members (which are protected), etc, whole inheritance isnt working anymore, and after few errors I got
fatal error C1903: unable to recover from previous error(s); stopping
compilation
I tried to add forward declaration but it doesnt help. I dont really know how to fix this.

C++ Class Inheritance Order

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;
}

Polymorphism with new data members

I would like to write a function that can initialize and return objects of different classes using polymorphism. I also would like these classes to have different data members which may be called through the virtual function. What I wrote below might work. Could you check if I have some undefined behavior in there? Thank you! One thing I am worried about is that when I call "delete polypoint" at the end it will not free the data member "scale" that is unique to "CRectangle". If my code doesn't work is there a way to make it work?
class CPolygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
virtual int area ()
{ return (0); }
};
class CRectangle: public CPolygon {
public:
int scale;
int area ()
{ return (width * height * scale ); }
};
CPolygon *polytestinner()
{
CPolygon *polypoint = 0;
int consoleinput = 2;
if (consoleinput>1)
{
CRectangle *rectpoint = new CRectangle();
rectpoint->scale = 4;
polypoint = rectpoint;
}
polypoint->set_values(3,4);
return polypoint;
}
void polytest()
{
CPolygon *polypoint = polytestinner();
gstd::print<int>(polypoint->area());
delete polypoint;
}
int main()
{
polytest();
return 0;
}
Thank you!
I feel compelled to point out Andrei Alexandrescu's object factory architecture. It allows your architecture to grow without having to modify the factory every time you create a concrete type. It is based on a "callback register", and it is actually implemented as a generic component in some libraries. The code is below.
Live Code Example
#include<map>
#include<iostream>
#include<stdexcept>
// your typical base class
class Shape {
public:
virtual void Draw() const = 0;
// virtual destructor allows concrete types to implement their own
// destrucion mechanisms
virtual ~Shape() {}
};
// this factory architecture was suggested by Andrei Alexandrescu in
// his book "Modern C++ Design" --- read it to get the full
// explanation (and a more generic implementation); this is just an
// example
class ShapeFactory {
public:
// this typedef allows to "name" arbitrary functions which take no
// arguments and return a pointer to a Shape instance
typedef Shape* (*CreateShapeCallback)();
Shape* CreateShape(int ShapeId) {
// try to find the callback corresponding to the given shape id;
// if no shape id found, throw exception
CallbackMap::const_iterator it = m_callbacks.find(ShapeId);
if(it == m_callbacks.end()) {
throw std::runtime_error("unknown shape id");
} else {
// create the instance using the creator callback
return (it->second)();
}
}
bool RegisterShape(int ShapeId, CreateShapeCallback Creator) {
// returns true if shape was registered; false if it had already
// been registered
return m_callbacks.insert(CallbackMap::value_type(ShapeId, Creator)).second;
}
bool UnRegisterShape(int ShapeId) {
// returns true if shape was unregistered, false if it was not
// registered in the first place
return m_callbacks.erase(ShapeId) == 1;
}
private:
// the typedef simplifies the implementation
typedef std::map<int, CreateShapeCallback> CallbackMap;
// the callbacks are stored in a map int->callback (see typedef
// above)
CallbackMap m_callbacks;
};
// create some concrete shapes... you would do this in other CPP files
class Line : public Shape {
public:
void Draw() const {
std::cout<<"Drawing a line"<<std::endl;
}
};
// another concrete shape...
class Circle : public Shape {
public:
void Draw() const {
std::cout<<"Drawing a circle"<<std::endl;
}
};
// ... other concrete shapes...
enum ShapeIds {LINE=1, CIRCLE, COUNT};
Shape* CreateLine() { return new Line; }
Shape* CreateCircle() { return new Circle; }
int main() {
// suppose this is the "singleton" instance for the ShapeFactory
// (this is an example! Singletons are not implemented like this!)
ShapeFactory *factory = new ShapeFactory;
factory->RegisterShape(ShapeIds::LINE, CreateLine);
factory->RegisterShape(ShapeIds::CIRCLE, CreateCircle);
Shape* s1 = factory->CreateShape(ShapeIds::CIRCLE);
Shape* s2 = factory->CreateShape(ShapeIds::LINE);
s1->Draw();
s2->Draw();
// will throw an error
try {
Shape *s3 = factory->CreateShape(-1);
s3->Draw();
} catch(const std::exception& e) {
std::cout<<"caught exception: "<<e.what()<<std::endl;
}
return 0;
}
CPolygon needs a virtual destructor:
virtual ~CPolygon() {}
You have undefined behavior in your code:
CPolygon *polypoint;
delete polypoint;
deleting a base class pointer when there is no virtual destructor will result in undefined behavior.
Your CPolygon class and CRectangle classes have no destructors, though the compiler will generate default destructor for you in this case, but they are not virtual by default. Therefore, you need to at least define a virtual destructor for your base class, i.e., CPolygon.

Creating array of different objects

I have this code, but I don't see where I went wrong here. It seem to compile OK but I cannot access Computer or Appliance functions. Can someone please help me understand how can I make an array that holds different objects on this code example I have here?
#include <iostream>
using namespace std;
class Technics
{
private:
int price, warranty;
static int objCount;
double pvn;
char *name, *manufacturer;
public:
Technics()
{
this->objCount++;
};
Technics(int price)
{
this->objCount++;
this->price = price;
}
~Technics(){
this->objCount = this->objCount - 2;
};
static int getObjCount()
{
return objCount;
}
void setPrice(int price)
{
this->price = price;
}
int getPrice()
{
return this->price;
}
void resetCount()
{
this->objCount = 0;
}
};
int Technics::objCount = 0;
class Computer : public Technics
{
private:
int cpu, ram, psu, hdd;
public:
Computer() {}
Computer(int price)
{
this->setPrice(price);
}
void setCpu(int cpu)
{
this->cpu = cpu;
}
int getCpu()
{
return this->cpu;
}
};
class Appliance : public Technics
{
private:
int height;
int width;
char* color;
char* type;
public:
Appliance(){}
Appliance(int height, int width)
{
this->height = height;
this->width = width;
}
void setWidth(int width)
{
this->width = width;
}
int getWidth()
{
return this->width;
}
};
void main()
{
//Creating array
Technics *_t[100];
// Adding some objects
_t[0] = new Computer();
_t[1] = new Computer();
_t[2] = new Appliance();
// I can access only properties of Technics, not Computer or Appliance
_t[0]->
int x;
cin >> x;
}
The line:
_t[0] = new Computer();
Creates a computer object and stores it as a Technics base pointer in the array (i.e. for all intents and purposes while in that array, it is a Technics object).
You need to cast back to the derived class to access members that are more derived than those in Technics:
static_cast<Computer*>(_t[0])->Your_Member();
Use dyncamic cast if you don't know which derived type it is - it will return the casted pointer on success and NULL on fail so it's kind of a type-check - it has big runtime overhead though, so try to avoid it :)
EDIT in response to your closing comment:
//Calculate the length of your dynamic array.
//Allocate the dynamic array as a pointer to a pointer to Technics - this is like
//Making an array of pointers each holding some Technics heirarchy object.
Technics** baselist = new Technics*[some_length];
//Populate them the same way as before:
baselist[0] = new Computer();
baselist[1] = new Appliance();
PS: you could also use std::vector which is dynamically changeable as opposed to just created at run time - it's the best option if your allowed to use it. It saves you making your own resizable array code. Google it ;)
That's because _t is a pointer to Technics not Computer or Appliance.
Give Technics an "object type" parameter e.g. an enum that is TechnicsType.Computer for Computer and TechnicsType.Applicance for Appliance, check that and cast to the appropriate type to get the class methods.
The solution is very very simple :)
The super-class must have the virtual functions of the subclasses declared in the class definition.
For example: if the super-class computer have a sub-class called laptop that have a function int getBatteryLife();, so the computer class must have the definition virtual int getBatteryLife() to be called in the vector of pointers of the type computer.
Because _t is a Technics pointer array and, there is not possible to access to derived classes attributes. Use a Visitor Pattern like this or downcast your pointer:
// visitor pattern
class Visitor
{
void accept(Appliance &ref) { // access Appliance attributes };
void accept(Computer & ref) { // access Computer attributes };
};
class Technics
{
....
virtual void visit(Visitor &) = 0;
};
class Appliance
{
....
virtual void visit(Visitor &v) { v.accept(*this); }
};
class Computer
{
....
virtual void visit(Visitor &v) { v.accept(*this); }
};
Yes, you can only access the properties of Technics, since your variable has type Technics. You have to cast it to your Computer or Appliance class in order to execute your additional methods.
You really have to think about your design here. Is it really appropiate? Why do you have all of the objects inside the same container? Especially if you have different methods to call..this doesn't make sense..
If you really want to call different methods, you probably have to use a switch statement to decide what type you have, then call the appropiate methods (I guess you want to iterate through the whole container, or else it doesn't make sense to have a big container with different objects).

Why is virtual function not being called?

//GUITEXT
class guitext : public entity {
public:
guitext(graphics *gfx, std::string _text, float _x, float _y,
float _size, float timeToLive);
bool update(float deltaTime, gameworld *world);
void draw(graphics *gfx);
};
void guitext::draw(graphics *gfx) { printf("draw"); }
//ENTITY
class entity {
public:
virtual bool update(float deltaTime, gameworld *world)
{ return false; }
virtual void draw(graphics *gfx) { }
};
//GAMEWORLD
void gameworld::addEntity(entity e) { entitys.push_back(e); }
//MAIN
for(int i = 0; i < (int)entitys.size(); i++) { entitys[i].draw(gfx); }
I have a vector in my gameworld class. When I add push a guitext entity to this vector I expect it to call the guitext::draw() function. But the base class function is being called. What am I doing wrong?
You made a vector of entity. Those objects always have type entity. If you want to invoke polymorphism, they need to be pointers or references. How can a vector of entity store a guitext? There's not enough space, it doesn't know how to destroy it, etc etc.
Was the vector declared as vector<entity>? Then only the base class part can be stored there, i.e. you lose polymorphism (which only works through pointer or reference in C++).
What you've done is a bit concealed variant of slicing.
You should define entitys to contain pointers to entity. Slightly edited example derived from your code.
#include "stdafx.h"
#include <vector>
#include <string>
class entity
{
public:
virtual void draw() { }
};
class guitext : public entity
{
public:
void draw()
{
printf("draw");
}
};
int _tmain(int argc, _TCHAR* argv[])
{
std::vector<entity *> entitys;
guitext g;
entitys.push_back(&g);
for(int i = 0; i < (int)entitys.size(); i++)
{
entitys[i]->draw();
}
return 0;
}
You're storing Entitys, not pointers to objects of varying derived types of Entity.
In addition, in your case it's not good idea to pass arguments by value, i suppose there will be very big quantity of objects that need to be redrawed. Better, by const reference, since functon doesn't change state of passed object inside.