I put the whole code on github: https://github.com/marianatuma/CG
I have a struct called point, declared in line.h, and a class line that has two points, start and end. EDIT: I didn't add it before, but Line inherits from GraphObj. graphObj.h:
class GraphObj {
private:
type t;
std::string name;
public:
GraphObj(type t, std::string name);
type getType();
std::string getName();
};
line.h:
#ifndef LINE_H
#define LINE_H
struct point {
double x;
double y;
};
class Line {
private:
point start;
point end;
public:
Line(type t, std::string name) : GraphObj(t, name) {};
void setStart(double x, double y);
void setEnd(double x, double y);
point getStart();
point getEnd();
};
#endif
line.cpp:
#include "line.h"
void Line::setStart(double x, double y) {
this->start.x = x;
this->start.y = y;
}
void Line::setEnd(double x, double y) {
this->end.x = x;
this->end.y = y;
}
point Line::getStart() {
return start;
}
point Line::getEnd() {
return end;
}
I always get a segmentation fault when I try accessing any of these points. I tried making them public, didn't work. I also tried using getters and it also didn't work. Here's how I'm initializing them:
The line is in a list of lines, called a display file, which will be used with cairo to draw them.
displayFile.h:
#ifndef DISPLAYFILE_H
#define DISPLAYFILE_H
#include <list>
#include "graphObj.h"
class DisplayFile {
private:
std::list<GraphObj*>* objectList;
std::list<GraphObj*>::iterator it;
int size;
public:
DisplayFile();
void add(GraphObj* g);
GraphObj* getNextObject();
void resetIterator();
int getSize();
};
#endif
displayFile.cpp:
#include "displayFile.h"
DisplayFile::DisplayFile() {
this->objectList = new std::list<GraphObj*>();
this->it = objectList->begin();
this->size = 0;
}
void DisplayFile::add(GraphObj* g) {
std::list<GraphObj*>::iterator tempIt;
tempIt = objectList->begin();
this->objectList->insert(tempIt, g);
this->size++;
}
GraphObj* DisplayFile::getNextObject() {
return *++it;
}
void DisplayFile::resetIterator() {
it = objectList->begin();
}
int DisplayFile::getSize() {
return size;
}
DisplayFile returns a GraphObj instead of the objectList, so it has to iterate through objectList by itself, hence the resetIterator (so when the main code is done traversing the list it will reset the iterator to the start of the list, but I'm not calling this method anywhere so far). The code in main.cpp where an instance of Line is used is below:
static void do_drawing(cairo_t *cr)
{
/* not using these right now
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_set_line_width(cr, 0.5);
*/
int size = df->getSize(); //df is the list
for(int i = 0; i < size; i++) {
Line* g = df->getNextObject();
point start = g->getStart();
}
}
The problem only starts when I try accessing the points, I can access other attributes from that line instance without problems. What am I doing wrong?
edit: I hope I've provided enough information, the main code is long and doesn't really have much to do with the line class, so I don't think it's relevant.
The problem lies with your list class.
class DisplayFile {
private:
std::list<GraphObj*>* objectList; // Why not just a list<GraphObj*>
std::list<GraphObj*>::iterator it; // Why use this?
int size; // WHY manually keep track of a STL container size?
public:
DisplayFile();
void add(GraphObj* g);
void resetIterator();
int getSize();
};
In your implementation file:
GraphObj* DisplayFile::getNextObject() {
return *++it;
}
As I already commented: this is the winner... Think about it, what if it already happens to be the last element on the list, and you ask for getNextObject()? Boom
I don't see why you couldn't just replace the entire DisplayFile class with a nice and plain std::list:
std::list<GraphObj*> objectList;
// I would also advice to change to smart pointers here
// for example: std::list<std::shared_ptr<GraphObj> > objectList;
// or std::list<std::unique_ptr<GraphObj> > objectList;
Then you would just use the STL methods to work with the list:
Add an item to the front: (for the sake of simplicity lets imagine that GraphObj has a default constructor)
GraphObj* g = new GraphObj();
objectList.push_front(g);
// If you change to smart pointers:
// objectList.push_front(std::make_shared<GraphObj>());
// or
// objectList.push_front(std::make_unique<GraphObj>());
Get the list size:
objectList.size();
Traverse the list:
for (std::list<GraphObj*>::const_iterator it = objectList.begin();
it != objectList.end();
++it)
{
point start = (*it)->getStart();
// or whatever you need to do here
}
Or with the much nicer range for:
for (const auto & graphObj : objectList)
{
point start = graphObj->getStart();
// or whatever you need to do here
}
Because you are not initilaizing the structs .
Change your constructor a bit
From this
Line(type t, std::string name) : GraphObj(t, name) {};
to
Line(type t, std::string name) : GraphObj(t, name) , start(),end() {};
This may help.
The problem might be coming from your getStart and getEnd because they return a point, which will create a copy(I think) of your start or end point, ie not using the point from line but copies. This usually isn't a big deal but if you want to change an x or y value and have the new value stick you'll need a reference to the original points x and y values.
Try this, change
point getStart();
point getEnd();
into
point *getStart() { return &start; }
point *getEnd() { return &end; }
and in your do_drawing(cairo_t *cr) change
point start = g->getStart();
to
point *start = g->getStart();
start->x = value; // or
double value = start->x; // or however you want to use start
Related
Suppose I had a boost variant instance containing a default initialised value (DataContainer). After a certain point in the program, it is guaranteed that the variant instance will contain a certain type (float) before a critical part of the program, but I only have access to the variant instance prior to it being set to this guaranteed type (DataDispatcher::set).
How can I create a float pointer to the location where the variant instance will be stored? Is it possible? My current attempt in Dispatcher::set causes a runtime error since the variant does not yet contain the float type.
Thanks
using Variant = boost::variant<std::string, float>;
struct DataContainer {
Variant value; // default initalised
};
class DataDispatcher {
public:
void set(DataContainer* dc) {
// this causes a fpointer to be equal to nullptr because dc->value is a string
// how to fix this?
fpointer = boost::get<float>(&dc->value);
}
// critical part of the program
void dispatch() {
importantCalculation(*val + 5);
}
private:
float* fpointer;
};
int main() {
DataContainer dc;
DataDispatcher dd;
dd.set(&dc); // only have access to variant instance here
dc.val = 1.4252; // guarantee it will contain a float
dd.dispatch(); // critical part
}
How can I create a float pointer to the location where the variant instance will be stored? Is it possible?
That's not reliably possible. It smells like a design issue when you "need" to store a pointer to data before it exists.
The natural solution is to store a reference to the variant instead: Live On Coliru
If you are convinced that the "optimization" of keeping a direct pointer to the float value is significant, you could do that manually:
Also Live On Coliru
#include <boost/variant.hpp>
#include <iostream>
#include <string>
void importantCalculation(float v) {
std::cout << "importantCalculation(" << v << ")\n";
}
using Variant = boost::variant<std::string, float>;
struct DataContainer {
Variant value;
};
class DataDispatcher {
public:
void reset() {
_cached = nullptr;
_ref = nullptr;
}
void set(DataContainer const& dc) {
_ref = &dc;
update_cache(); // in case it is already float
}
// critical part of the program
void dispatch() { importantCalculation(get() + 5); }
private:
DataContainer const* _ref = nullptr;
float const* _cached = nullptr;
void update_cache() {
_cached = nullptr;
if (_ref)
if (auto* fp = boost::get<float>(&_ref->value))
_cached = fp;
}
float get() {
if (!_cached)
update_cache();
assert(_cached);
return *_cached;
}
};
int main() {
DataContainer dc;
DataDispatcher dd;
dd.set(dc); // only have access to variant instance here
dc.value = 1.4252; // guarantee it will contain a float
dd.dispatch(); // critical part
// important:
dd.reset();
dc.value = "3.6474";
dc.value = 2.5363;
dd.set(dc); // important
dd.dispatch();
}
Prints
importantCalculation(6.4252)
importantCalculation(7.5363)
Note that other variant implementations might document a guaranteed element storage layout for small element types, and you could then rely on that documented guarantee.
I'm trying to save an Object in an 2D Vector. The vector needs to be sized at runtime. Therefore i use the resize function as mentioned in many other issues.
Her an broke down code example of my problem. So the code might not make sense but I get the same error.
Animation.h
class myPoint{
public:
int x, y;
myPoint(){}
myPoint(int x, int y) : x(x), y(y) {}
};
class AnimationFrame {
private:
std::vector<std::vector<myPoint>> sprites; //the important part
public:
void addSpritePoint(myPoint gridPos, myPoint tilePos);
...
};
class Animation {
private:
std::vector<AnimationFrame*> animationFrames;
public:
...
};
Animation.cpp
Animation::Animation() {}
int Animation::addAnimationFrame() {
AnimationFrame *newAnimationFrame = new AnimationFrame();
this->animationFrames.emplace_back(newAnimationFrame);
}
//AnimationFrame class
AnimationFrame::AnimationFrame(){
int w = 3; //just for the test
int h = 3;
this->sprites.resize(w, std::vector<myPoint>(h, myPoint(0,0)));
}
void AnimationFrame::addSpritePoint(myPoint gridPos, myPoint tilePos) {
this->sprites[gridPos.x][gridPos.y] = tilePos;
//printf(""); //breakpoint here
}
main.cpp
int main() {
Animation *a = new Animation();
a->addAnimationFrame();
a->getAnimationFrame(0).addSpritePoint(myPoint(0,0), myPoint(1,1));
a->getAnimationFrame(0).addSpritePoint(myPoint(0,1), myPoint(2,2));
a->getAnimationFrame(0).addSpritePoint(myPoint(0,2), myPoint(3,3));
}
I expect that the sprites 2D vector from my AnimationFrame class holds the values. When the first breakpoint kicks in the the Point(1,1) is in sprites(0,0) but when i now skip to the next breakpoint the values in sprites(0,0) is (0,0) again. So it resets the value. And i have no clue why.
The problem comes from the fact that Animation::getAnimationFrame() returns a copy of its internal data:
AnimationFrame Animation::getAnimationFrame(int frame) const;
So this modifies a temporary object and has no effect once the full expression has been evaluated:
a->getAnimationFrame(0).addSpritePoint(myPoint(0,0), myPoint(1,1));
The fix is simple: return by reference:
const AnimationFrame& Animation::getAnimationFrame(int frame) const
{
return *animationFrames[frame];
}
AnimationFrame& Animation::getAnimationFrame(int frame)
{
return *animationFrames[frame];
}
(yes, you need a const and a non-const version)
class ListOfGifts
{
private:
Gift list[50];
int count = 0;
public:
void suggest(ListOfGifts& affordable, float dollarLimit) const
{
// how do I initialize affordable to an empty list without a constructor
}
}
Trying to initialize a list from a parameter that is a reference. How can I do this?
Use an std::array:
class ListOfGifts
{
private:
std::array<Gift, 50> list;
int count = 0;
public:
void suggest(ListOfGifts& affordable, float dollarLimit) const
{
affordable.list = std::array<Gift, 50>{};
}
}
FYI, C++ is literally built on constructors. They will come up eventually, and they're actually quite helpful.
I have a little conceptual problem. I have different classes representing the geometric data of an edge depending what type of edge it is. For Example the class for a straight line and a circle:
class Line{
private:
double[3] startPoint;
double[3] endPoint;
public:
//getter and setter and some other functions such as equals
}
class Circle{
private:
double[3] center;
double[3] planeNormal;
double radius;
public:
//getter and setter and some other functions such as equals
}
Now I need a class Edge which stores the type of the edge and the fitting geometric data.
In the end the Edge has to be stored in a std::vector<Edge> edges; The Problem is that I do not know the type before runtime, because I am analysing the boundary representation of CAD parts which can have various types of edges.
class Edge{
private:
EdgeType type;
GeometricData data;
public:
//...
}
So how should I design my class Edge and espacially GeometricData which has to store either a Line-object, a Circle-object or another geometric object, so that I can go back from GeometricData to Line, Circle or whatever geometric class it may be.
I tried polymorphism with GeometricData as base class, but the derived
classes are too different, since things like B-Splines are also
included.
I also tried GeometricData as void* and a template-approach
for the set- and get-methode, but with that I have problems
storing the data and not only the pointer, because of the lifetime
of the objects (I have to analyse the BRep recursivly).
I would also appreciate suggestions that may change the whole concept of the geometric representations, as long as I can access the type-fitting data such as startPoint of a straight line or radius of a circle using the edges-vector.
EDIT:
Thanks for the fast responses. I decided to use suszterpatt suggestion including some of my templates and changing my std::vector<Edge> to std::vector<shared_ptr<Edge>> as TAS mentioned. Now it looks like this:
#include "stdafx.h"
#include <string>
#include <sstream>
#include <iostream>
#include <vector>
using namespace std;
enum EdgeType{
LINE = 100,
CIRCLE
};
//Basis
class GeometricData {
private:
public:
virtual string toXMLString() = 0;
};
class Line : public GeometricData{
//less code just for illustration
private:
double d1;
public:
double getD1() { return d1; }
void setD1(double d1) { this->d1 = d1;}
virtual string toXMLString() {
stringstream s;
s << "d1=\"" << d1 <<"\"";
return s.str();
}
};
class Circle : public GeometricData{
private:
double d2;
public:
double getD2() { return d2; }
void setD2(double d2) { this->d2 = d2;}
virtual string toXMLString() {
stringstream s;
s << "d2=\"" << d2<<"\"";
return s.str();
}
};
class Edge{
private:
EdgeType t;
GeometricData* d;
public:
Edge () { d = 0;}
~Edge () {if (d) {delete d; d=0;}}
template <typename T> int setGeomData (T data) {
static_assert(
is_same<T,Line*>::value ||
is_same<T,Circle*>::value,
"EdgeGeometryType is not supported");
GeometricData* buffer = data;
//set type corresponding to thethis->data given= data
if(is_same<T,Line*>::value){
this->t = LINE;
Line* lb = dynamic_cast<Line*>(buffer);
Line* l = new Line(*lb);
this->d = l;
}else if (is_same<T,Circle*>::value){
this->t = CIRCLE;
Circle* cb = dynamic_cast<Circle*>(buffer);
Circle* c = new Circle(*cb);
this->d = c;
}else{// this case should not occure because of the static_assert
return -1;
}
return 0;
};
template <typename T> T getGeomData () {
static_assert(
is_same<T,Line*>::value ||
is_same<T,Circle*>::value,
"EdgeGeometryType is not supported");
if ((this->t == LINE && is_same<T,Line*>::value) ||
(this->t == CIRCLE && is_same<T,Circle*>::value))
{
return dynamic_cast<T>(this->d);
}else{
return NULL;
}
};
EdgeType getType(){ return t; }
//void setType(EdgeType t) { this->t = t; } not needed
GeometricData* getData(){return d;}
};
class Model {
private:
vector <shared_ptr<Edge>> edges;
public:
Model(){}
vector <shared_ptr<Edge>> getEdges(){ return edges; }
void addEdge (Edge* e) {edges.push_back(shared_ptr<Edge>(e));}
shared_ptr<Edge> getEdge(int i ){ return edges.at(i); }
};
// Functions
void foo2 (Edge* e){
Line* l = new Line;
l->setD1(0.1);
e->setGeomData<Line*>(l);
//e->setType(LINE); not needed
delete l;
}
void foo1 (Edge* e){
Circle c;
c.setD2(0.2);
e->setGeomData<Circle*>(&c);
//e->setType(CIRCLE); not needed
}
void foo (Model* mdl){
Edge* e1 = new Edge;
Edge* e2 = new Edge;
foo1(e1);
foo2(e2);
mdl->addEdge(e1);
mdl->addEdge(e2);
}
int _tmain(int argc, _TCHAR* argv[])
{
Model mdl;
int i;
foo(&mdl);
cout << "Edge 1: " << mdl.getEdge(0)->getData()->toXMLString() << endl;
cout << "Edge 2: " << mdl.getEdge(1)->getData()->toXMLString() << endl;
for (i = 0; i<2; i++){
switch (mdl.getEdge(i)->getType()){
case LINE: {
Line* ld = (mdl.getEdge(i)->getGeomData<Line*>());
cout << "Line (templated get): " << ld->getD1() << endl;
}break;
case CIRCLE:{
Circle* cr = (mdl.getEdge(i)->getGeomData<Circle*>());
cout << "Circle (templated get): "<< cr->getD2() << endl;
}break;
}
}
return 0;
}
There's a number of solutions. The one that seems to fit best is Boost.Variant; define your Line and Circle classes as you showed, then make GeometricData a typedef of variant<Line, Circle>, and you'll be able to store an instance of either one in there. When you want to go back from a GeometricData to the actual object stored, you can perform a cast, or you can write a so-called visitor. A visitor is just a class specifying an action for each possible type, and then boost::apply_visitor can be used to select the right action based on what is stored.
Example (using vectors for simpler notation):
struct Line {
Vector3d startPoint, endPoint;
};
struct Circle {
Vector3d center;
float radius;
};
using GeometricData = boost::variant<Line, Circle>;
struct MidpointVisitor : boost::static_visitor<Vector3d> const {
Vector3d operator()(Line const& line) {
return (line.startPoint + line.endPoint)/2;
}
Vector3d operator()(Circle const& circle) const {
return circle.center;
}
};
void foo() {
GeometricData data;
// ...
auto midpoint = boost::apply_visitor(MidpointVisitor{}, data);
// ...
}
A less type-strict solution is Boost.Any, but I don't see any advantages for this case. Even if you did need another option, you'd probably want to specify that explicitly.
I suspect your solution using void* (or using a common base class and RTTI) could be made to work using smart pointers. However, the only advantages I can see are faster compilation and less awful compiler error messages, while you end up having to bother with dynamic allocation and can't have visitors.
You could also roll your own union for this, effectively implementing something along the lines of Variant. That would involve making sure you get construction, destruction and alignment all correct, and don't trigger some obscure case of undefined behaviour. If that's not a problem for you and you really don't want to use a library, it's an option, but it is very much reinventing the wheel.
I would say polymorphism where perhaps the shared interface looks something like this:
class Edge
{
enum EdgeType
{
CIRCLE,
LINE
};
EdgeType GetType();
}
Then in a switch statement somewhere you could do something like:
switch (myEdge.GetType())
{
case Edge::EdgeType::CIRCLE:
auto myCircle = (Circle)myEdge;
// do things specific to circle
break;
case Edge::EdgeType::LINE:
auto myLine = (Line)myEdge;
// do things specific to line
break;
}
That being said, I would try to use polymorphism as much as possible over the switch statement, but the above interface gives you the option of having a function using edges contain the logic for doing different things based on type.
I'm not sure I fully understand the problem you're trying solve but from reading and understanding the question, I'd say look into serialization
You could maybe create a global array type variable, store the objects you need, serialize it an deserialize it when you need to use it.
This question already has answers here:
Why is virtual function not being called?
(6 answers)
Closed 9 years ago.
AoA,
I am making a console game of chess, But I am stuck at polymorphism, below is the classes and functions definitions
/* old Part
//Base Class
class Piece /*Parent class */
{
protected:
Position* pCoord;
std::string color;
char symbol;
public:
Piece(Position* Coord,std::string Color,char symbol);
Position GetCurrentPos();
std::string GetColor();
void SetColor(std::string color);
void Draw();
virtual bool SetPos(Position* newPos){MessageBox(NULL,L"Virtual Running",L"Error",MB_OK); return true;};
virtual ~Piece();
};
/* Inherited classes */
//Child classes
class Pawn: public Piece
{
private:
std::vector<Position>* allowPos;
public:
Pawn(Position* Coord,std::string Color,char symbol);
~Pawn();
std::vector<Position>* GetThreatendFields();
bool isValidMove(Position* newPos);
bool SetPos(Position* newPos);
};
//Child classes
class Bishops: public Piece
{
private:
std::vector<Position>* allowPos;
public:
Bishops(Position* Coord,std::string Color,char symbol);
~Bishops();
std::vector<Position>* GetThreatendFields();
bool isValidMove(Position* newPos);
bool SetPos(Position* newPos);
};
//Here is the implementation of child class function SetPos
bool Pawn::SetPos(Position* newPos)
{
bool isSet = false;
this->pCoord = new Position();
this->pCoord = newPos;
isSet = true;
MessageBox(NULL,L"Child function running",L"Yuhuu!",MB_OK);
return isSet;
}
class ChessBoard
{
private:
Position ptr; //dummy
int SelectedPiece;
vector<Piece> pPieceSet;
bool isSelected;
public:
ChessBoard();
~ChessBoard();
void ShowPieces(Player *p1,Player *p2);
void Draw();
void MouseActivity();
void Place(Piece& p);
};
//it just shows the peices acquired from player objects..dummy vector pointer
void ChessBoard::ShowPieces(Player* p1,Player* p2)
{
std::vector<Piece>* vPiece = p1->GetPieces();
for( int i=0;i<vPiece->size();i++ )
{
Piece& piece = vPiece->at(i);
Place(piece);
piece.Draw();
}
vPiece = p2->GetPieces();
for( int i=0;i<vPiece->size();i++ )
{
Piece& piece = vPiece->at(i);
Place(piece);
piece.Draw();
}
}
*/
/*new part
I did what you say
Player::std::vector<Piece*> *vPieceSet;
Player::Player(int turn)
{
this->turn = turn%2;
this->vPieceSet = new std::vector<Piece*>;
}
void Player::Initialize() //Initial and final ranges for position
{
//Initialization of pieces to their respective position
Position pos;
Piece *pPiece;
if( this->turn == 0 )
{
this->SetName("Player 1");
for( int i=8;i<16;i++ )
{
pos.SetPosition(i);
Pawn pPawn(&pos,"blue",'P');
pPiece = &pPawn;
this->vPieceSet->push_back(pPiece);
}
//other classes same as above
}
It runs fine at initialzation function(stores all classes fine) but when use function to get the vector object
std::vector<Piece*>* Player::GetPieces()
{
std::vector<Piece*>* tPieces = this->vPieceSet;
return tPieces;
}
//In main.cpp
it doesnot return the vector object
Player p1(0),p2(1);
p1.Initialize();
p2.Initialize(); //initialization done perfectly while debugging
vector<Piece*> *obj = p1.GetPieces(); //returns garbage
Piece* pObj = obj->at(0); //garbage
cout<<pObj->GetColor(); // garbage
*/new part
Sounds like I have another problem!
When you use polymorphism, what you are really trying to do is instantiate an object of derived type and call the methods on that object through a pointer or reference to the base object.
class Foo
{
public:
virtual void DoIt () { cout << "Foo"; }
};
class Bar
:
public Foo
{
public:
void DoIt () { cout << "Bar"; }
};
int main()
{
Foo* foo = new Bar;
foo->DoIt(); // OUTPUT = "Bar"
Foo& fooRef = *foo;
fooRef.DoIt(); // OUTPUT = "Bar"
}
In order for this to work, you need to use either a pointer or a reference to the object. You can't make a copy of the object using a the base class. If you make a copy, you will slice the object.
int main()
{
Foo* foo = new Bar;
foo->DoIt(); // OK, output = "Bar"
Foo fooCopy = *foo; // OOPS! sliced Bar
fooCopy.DoIt(); // WRONG -- output = "Foo"
}
In your code, the Piece class is intended to be polymorphic, and in your ChessBoard class you have a vector of this class:
class ChessBoard
{
private:
vector<Piece> pPieceSet;
};
Since this is a vector of the Piece object itself, and not a pointer-to-Piece, anything you put in here will be sliced. You need to change pPieceSet to be a vector of pointers-to-Piece:
vector <Piece*> pPieceSet;
You have further problems in Initialize, which need to be refactored anyway. For one thing, you have another vector of Piece objects, and there are two problems here. First, it needs to be a vector of pointers, and second, why do you need another vector at all when there is already one associated with the ChessBoard? I didn't thouroughly examine your code so maybe you do need it, but this seems like an error. There should probably just be one collection of pieces, in the ChessBoard.
In your Initialize method:
Piece *pPiece;
// ...
Pawn pPawn(&pos,"blue",'P');
pPiece = &pPawn;
vPieceSet.push_back(*pPiece);
There are a couple of problems. One, you are pushing back a sliced copy of the Piece, which will be fixed when you change your vector to store pointers. Second, if you just change this like so:
Piece *pPiece;
// ...
Pawn pPawn(&pos,"blue",'P');
pPiece = &pPawn;
vPieceSet.push_back(pPiece); // <-- not dereferencing
You will have a new problem because you'll be storing the pointer to a local (automatic) variable. Best is to do this:
Piece* pPiece = new Pawn (...);
// ...
vPieceSet.push_back (pPiece);
Please don't forget to delete everything you new. This is best handled by using smart pointers rather than raw pointers. In C++03 we have auto_ptr, but those can't go in a vector. Instead you'll need to use Boost or something else, or just store raw pointers. In C++11, we now have unique_ptr (preferred) and shared_ptr, which can go in to a vector.
In C++11, the best solution here is to have a vector declared as:
vector <unique_ptr <Piece> > pPieceSet;
...unless you have some compelling need to use shared_ptr instead.
As others have mentioned, it is a slicing issue, and the issue is created here:
class Player
{
private:
std::string pName;
std::vector<Piece> vPieceSet; // <-- This is your problem
int turn;
public:
Player(int turn);
~Player();
void Initialize();
std::string GetName();
void SetName(std::string Name);
int GetTurn();
std::vector<Piece>* GetPieces();
};
You are storing them in the vector as instances of Piece, which is slicing off the details of the piece (e.g. the Bishop implementation). You should modify it to something like:
class Player
{
private:
std::string pName;
std::vector<Piece*> vPieceSet; // or better, use a smart pointer wrapper
int turn;
public:
Player(int turn);
~Player();
void Initialize();
std::string GetName();
void SetName(std::string Name);
int GetTurn();
std::vector<Piece*> GetPieces(); // note this change as well
};
With your additional question/edit, you are getting another unrelated problem:
void Player::Initialize() //Initial and final ranges for position
{
Position pos; // position is declared inside the scope of Initialize
Piece *pPiece;
if( this->turn == 0 )
{
this->SetName("Player 1");
for( int i=8;i<16;i++ )
{
pos.SetPosition(i);
Pawn pPawn(&pos,"blue",'P'); // you are passing the address of position to the Pawn, and Pawn is within the scope of this loop
pPiece = &pPawn; // you are storing the address of the Pawn
this->vPieceSet->push_back(pPiece);
}
// Pawn is now out of scope and pPiece points to the memory location Pawn *used* to be at (but will likely be overwritten soon).
// As soon as this function returns, you have the same problem with pos
}
You need to allocate those variables on the heap (hence the reason we suggested smart pointer wrappers).