Classes accessing each other with pointers - c++

I'm still confused with pointers, maybe you could enlighten me a bit.
I'm having some classes pointing to each other and don't get the way to access them in the right way.
#include <vector>
#include <iostream>
class Player;
class Trainer;
class Team {
Trainer* trainer_;
std::vector<Player*> player_;
public:
std::vector<Player*> player() { return player_; }
Trainer* trainer() { return trainer_; }
std::vector<Player*> get_playerlist(){
return player_;
};
};
class Player {
public:
void setteam_(Team* x){
team_ = x;
}
private:
Team* team_;
};
class Trainer {
Team* Team_;
};
int main()
{
Player player1;
Team team1;
std::vector<Player*> playerlist;
player1.setteam_(&team1);
playerlist = team1.get_playerlist();
std::cout << playerlist.size();
std::cin.get();
return 0;
}
In the main there is player1 created and assigned to the playerlist of team1, now he should somehow appear there when i get the playerlist. But the output of this code is that the size of the playerlist of team 1 is still 0. What did I do wrong ?

Your Team class has no method that actually adds players to the player_ vector. Setting the team_ pointer to the team1 instance is not sufficient.

player1.setteam_(&team1);
What happens next is:
void setteam_(Team* x){
team_ = x;
}
Here you are stating that this Player has pointer to Team set to the same address as x. But this doesn't mean that this Team object has pointer to player in std::vector. This doesn't happen automaticly, you need something like:
void setteam_(Team* x){
team_ = x;
x->addPlayer( this); // add to vector
}

Related

Const_iterator member variable not pointing to the begin of a vector member variable after initialization

I am trying to implement a Bayesian estimator for the card game Avalon. The game has five rounds and each round contains at most five proposals made by five different players. If a proposal is accepted, players go on a quest and the game proceeds to the next round. Before the previous round is completed, it is not known which 5 players will get to propose teams in the next round. I wanted to keep track of the current player that gets to propose a team using an iterator, but somehow it ends up pointing to nowhere. Specifically, in the constructor called for round1, the iterator Round::proposer points correctly to &PlayerA, the beginning of Round::proposers. However, when I add this instance (or a copy of it?) to Game::rounds, then the Round member proposer of Game::rounds.back() points nowhere, even though the Round member proposers is still correct. Why does that happen? During execution, of course a read access violation exception is thrown during the call (*Round::proposer)->make_proposal();. I apologize for the lengthy question, but two levels of indirection seemed necessary to produce the error.
// Player.h
#include <string>
class Player
{
private:
std::string name;
public:
Player(std::string name) : name(name) {};
void make_proposal() const {};
};
// Round.h
#include "Player.h"
#include <vector>
class Round
{
private:
std::vector<const Player*> proposers;
std::vector<const Player*>::const_iterator proposer;
public:
Round(std::vector<const Player*> proposers) : proposers(proposers), proposer(Round::proposers.begin()) {};
void next_proposal() { (*Round::proposer)->make_proposal(); };
};
// Game.h
#include "Round.h"
#include <vector>
class Game
{
private:
std::vector<Player*> players;
std::vector<Player*>::iterator active_player;
std::vector<Round> rounds;
public:
Game(std::vector<Player*> players);
void advance_player();
void next_round();
};
// Game.cpp
#include "Game.h"
Game::Game(std::vector<Player*> players)
: players(players), active_player(Game::players.begin())
{
std::vector<Player*>::const_iterator player = Game::players.begin();
std::vector<const Player*> proposers = { *player };
for (unsigned int i = 0; i < 4; ++i) {
++player;
if (player == Game::players.end()) player = Game::players.begin();
proposers.push_back(*player);
}
Round round1(proposers);
Game::rounds = { round1 };
}
void Game::next_round()
{
Game::rounds.back().next_proposal();
}
#include <iostream>
#include "Game.h"
int main()
{
Player playerA("A");
Player playerB("B");
Player playerC("C");
Player playerD("D");
Player playerE("E");
Player playerF("F");
std::vector<Player*> players = { &playerA, &playerB, &playerC, &playerD, &playerE, &playerF };
Game game(players);
for(unsigned int i = 0; i < 5; ++i) {
game.next_round();
}
}
Surprisingly, replacing the two lines of code
Round round1(proposers);
Game::rounds = { round1 };
in Game.cpp with
Round* round1 = new Round(proposers);
Game::rounds = { *round1 };
fixes the issue, although I really don't understand why. After all, rounds is a member variable of Game and exists until instance game is destroyed. Follow-up question to this hack: is the instance to which round1 points in the last code snippet destroyed by the default constructor of class Game since it is dereferenced before adding to the member variable?
Your Round cannot be copied without problems:
class Round
{
private:
std::vector<const Player*> proposers;
std::vector<const Player*>::const_iterator proposer;
public:
Round(std::vector<const Player*> proposers) : proposers(proposers), proposer(Round::proposers.begin()) {};
void next_proposal() { (*Round::proposer)->make_proposal(); };
};
If you do copy it, the proposer will still be an iterator to an element in the original Round not to the vector in the copy. When you do this:
Round* round1 = new Round(proposers);
Game::rounds = { *round1 };
Then the local object round1 is not destroyed at the end of the scope, hence the iterator that is now inside rounds, after making a copy of round1, refers to an element that is still alive. Though it refers to the element inside round1, not to the Round that you placed in rounds.
Either take care of the rule of 3/5 for Round, or use indices instead of iterators. Indices get not invalidated when the whole vector is copied. (They also get not invalidated when you push back more elements to the vector, but iterators do)
A simpler example for similar problem:
#include <iostream>
struct broken {
int x;
int* ptr;
broken(int a = 0) : x(a),ptr(&x) {}
};
int main() {
broken a{42};
broken b{123};
a = b;
a.x = 0;
std::cout << *(a.ptr);
}
After copying b to a the pointer in a will still point to b.x, hence output is 123 (not 0 as one might expect).

Classes in C++ Constructor and D'tor

I have two Classes, Player and Game.
class Game
{
private:
int maxPlayer;
Player** playersArray;
public:
Game(int maxPlayer);
~Game();
}
Each index in playersArray consists of pointers to class Player.I'm not sure though how to make the constructor and destructor of the Class Game. This is my first try but the code isn't working any idea?
Game::Game(int maxPlayer)
{ this->playersArray = new Player*[maxPlayer];
for(int i=0;i<maxPlayer;i++)
{
playersArray[i]=NULL;
}
}
Game::~Game() {
for(int i=0;i<maxPlayer;i++)
{
delete[] *playersArray[i];
}
delete (playersArray);
}
It has been along time since I have programmed in C++. The only error I see for sure is that the constructor has a parameter maxPlayer and never touches the member variable maxPlayer. The destructor uses the member variable maxPlayer, which probably has never been initialized. The constructor ought to assign the parameter to the member variable.
When you delete an array you are supposed to use delete[] but you use delete for a single object. So, I think you have them swapped.
OK, since I did not get response to my comment, let me try this: If you modify your code as shown below, does it do what you expect it to do?
class Player
{
};
class Game
{
private:
int maxPlayer;
Player** playersArray;
public:
Game(int maxPlayer);
~Game();
};
Game::Game(int maxPlayer)
{
this->maxPlayer = maxPlayer;
this->playersArray = new Player*[maxPlayer];
for (int i = 0;i<maxPlayer;i++)
{
playersArray[i] = NULL;
}
}
Game::~Game() {
for (int i = 0;i<maxPlayer;i++)
{
delete playersArray[i];
}
delete[] playersArray;
}
int main()
{
Game g(10);
return 0;
}

constructor inside a method c++

I have a constructor inside a method that I want to have access at all time
//ItemEditor.cpp
#include "ItemContainer.h"
void ItemEditor::CreateItem() {
ItemContainer* wornItems = new ItemContainer();
}
inside of my driver I call my method createItem();
//driver
int main(){
ItemEditor* createItem = new ItemEditor();
createItem->CreateItem();
}
afterwards I want to have access to backpack outside of the createItem
How can I accomplish that?
Make the item container a member variable so its scope is the life time of the object.
There is no reason to use dynamic allocation, so just use an instance of the ItemContainer instead of a pointer.
#include <iostream>
class ItemContainer {
int item = 0;
public:
void addItem(int i) {
item = i;
}
int getItem() {
return item;
}
};
class ItemEditor {
public:
ItemEditor() {
}
void createEditor() {
wornItems.addItem(3);
}
ItemContainer wornItems;
};
int main() {
ItemEditor editor;
int item = editor.wornItems.getItem(); //or some method
std::cout << item << std::endl;
editor.createEditor();
item = editor.wornItems.getItem(); //or some method
std::cout << item;
return 0;
}
You can also make the container private and use public methods to access its contents. You can see an example here
By backpack I assume whatever is returned by
createItem->CreateItem();
Why not just store it in a pointer since you used the new to allocate the object in a heap?
ItemContainer* ItemEditor::CreateItem() {
return new ItemContainer();
}
Main file:
int main(){
ItemEditor* createItem = new ItemEditor();
ItemContainer* backpack = createItem->CreateItem();
}
Also I want to suggest it is a better practice to provide a move semantic for ItemContainer and get rid of pointers. That way you are relying on RAII and stack for object destruction, less risk of memory-leak. Related article:
http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html
Here is a full compiling code:
//Header.h
#include <iostream>
class ItemContainer{
public:
void sayHello(){
std::cout << "HulloWorld!\n";
}
};
class ItemEditor{
public:
ItemEditor(){};
ItemContainer* ItemEditor::CreateItem(){
return new ItemContainer();
}
};
MainFile:
//main
#include "Header.h"
int main()
{
ItemEditor* createItem = new ItemEditor();
ItemContainer* backpack = createItem->CreateItem();
backpack->sayHello();
}

Copying vector and remaining the memory adress of the members

I try to read in some data of teams and players and change the data.
The Player class members have pointers to the teams from the Team class, while the Teams have a playerlist filled with pointers to the players.
The problem comes with the readin()-function which reads in the team and player data from a txt.file and returns a vector of teams. After the readin-process the pointers created in the readin-process seem to direct to wrong addresses.
So reading out data from the vector of teams returned by the read-in function is not the same anymore than reading out the data from the pointers created in the read-in function.
Here is the general structur of the classes:
#include <iostream>
#include <vector>
#include <string>
class Player;
class Team
{
public:
std::vector<Player*> getplayerlist(){
return playerlist;
}
void setteamname(std::string x){
teamname = x;
}
std::string getteamname(){
return teamname;
}
void Team::addPlayer(Player* x){
playerlist.emplace_back(x);
};
private:
std::vector<Player*> playerlist;
std::string teamname;
};
class Player
{
public:
Team* getpteam(){
return pteam;
}
void setpteam(Team* x){
pteam = x;
}
void setinformation(std::string x, int y){
name= x;
id = y;
}
private:
int id;
std::string name;
Team* pteam;
};
And here is the structure of the read-in function
vector<Team> readin(){
//some readin stuff
//if the line contains the teamname
Team team;
team.setteamID_(a);
team.setteamname_(word2);
Teamvector.emplace_back(team);
//if the line contains player data
//add the player to the team created before
Player* player = new Player();
player->setinformation_(b, word1, lname, str, &Teamvector[a-1]);
Teamvector[a-1].addPlayer(player);
return Teamvector;
}
But if i compare the addresses of &Teamvektor[0] and
vector <Team> team = readin();
&team[0]
they are different. How can i "remain" the adress of the stored teams ?
You are returning std::vector by value: this means container is being copied, thus elements have same values but different addresses in memory.
There are few ways how to handle this. For example:
Create container and fill it in your method:
std::vector<Team> v;
void readin_fillVector( vector<Team>& v) {
//.. v.push_back( team);
}
Pass iterator
void readin_fillVector( std::back_insert_iterator< std::vector<Team> > it) {
//.. (*it)++ = team;
}

Virtual function issue in C++ [duplicate]

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).