I am currently benchmarking a program on a Linux system with Valgrind.
I have this strange cache miss with the getter method const int GetID() const,
but I can't really explain where it came from. Does anyone have any idea what's causing this problem?
I thought it might be caused by the constant keyword at the end, but it hasn't changed.
The cache miss occurs in the L1 during the read operation. I have added a screenshot below the code snippet.
class GameObject
{
friend class GameManager;
private:
int id;
GameObject();
static int CreateID() { return /* do some id stuff in here */}
...
public:
~GameObject();
const int GetID() const { return id; }
...
};
KCachegrind Screenshot:
UPDATE:
These are methods of the GameManager class that call the const int GetID() const method. It is called when a GameObject must be destroyed or returned to a specific point. The GameManager contains a vector of all GameObjects, they are created when the application starts, after which the vector does not change at all.
After they are created, the attached components call the GameObject* GetGameObject(int const _gameObjectId) method once to retrieve all required components. So I guess the GameObjects should already be in the cache or did I miss a point?
Maybe the call is so strong that it creates more cache misses at the beginning of the program than the rest of the application at runtime?
void GameManager::DestroyGameObject(const int _id)
{
for (auto it = gameObjects.begin(); it != gameObjects.end(); it++)
{
if (it->GetID() == _id)
{
gameObjects.erase(it);
return;
}
}
}
GameObject* GameManager::GetGameObject(const int _gameObjectId)
{
for (int i = 0; i < gameObjects.size(); i++)
{
if (gameObjects[i].GetID() == _gameObjectId)
{
return &gameObjects[i];
}
}
return nullptr;
}
Related
I am building a tile engine in C++. What is the most efficient way to store the logical properties of the individual tiles in the game? I understand the rendering side of the program, but I am having trouble taking a simple id number and turning it into an actual set of properties ( like whether or not a tile is walkable or flammable or can trigger an event, etc. )
One idea is to have a tile object that has the potential to be any kind of tile, and turns on certain boolean "switches" based on the type ( note that the following is mostly just pseudocode and not meant to actually compile):
class Tile
{
private:
int m_type;
bool m_walkable;
// etc...
public:
Tile( int type ) : m_type( type)
{
if( type == 0 )
{
m_walkable = true;
} else if( type == 1 ) {
m_walkable = false;
}
// etc etc would probably be a switch
// statement but you get the idea
}
};
Personally, I do not like this idea; I think it would be much more elegant for each type of tile to have its own data structure. I imagine using some kind of inheritance based system but I just can't seem to put it all together. Fundamentally, I think it should look something like this:
enum class TileType
{
TILE_TYPE null, // 0
TILE_TYPE floor, // 1
TILE_TYPE wall, // 2
// etc ...
};
class BTile
{
private:
// Location and dimensions of tile
int m_xOffset;
int m_yOffset;
int m_width;
int m_height;
// Type of tile, initialized to 0 for base class
TileType m_type;
public:
// ...
};
class Floor : public BTile
{
private:
TileType = 1;
bool walkable = true;
// etc...
};
class Wall : public BTile
{
private:
TileType = 2;
bool walkable = false;
};
Something like this would feel much more organized and flexible, while also allowing me to plug Floor and Wall objects into any kind of function expecting a Tile object. The problem is that I just cannot seem to put this all together in a way that actually works - for example, how can I provide a specific tile type with the tile it is associated with? If I am reading a text file into my program for example, how can I get from 001 to Tile->Floor? Any advice or input on this subject would be greatly appreciated.
Try using a factory method.
The simplest way to do this is to use a switch.
Tile* createTile(TileType tileType) {
switch(tileType) {
case TileType.floor: return new Floor;
case TileType.wall: return new Wall;
}
return nullptr;
}
This is usually not recommended as you have to update the factory each time you add a new type.
Alternatively you could use some trick to register the types to the factory.
One approach is the one described here. There are a lot more strategies.
Why are you reinventing OO? Objects already have a type, no need for TileType. You may want to read up on virtual functions.
There are several approaches here, depending on what exactly you want the tiles in your game to do. You can go the object oriented way, by having distinct classes for the different tile types that you have, or you can go simpler and just have a bitset that represent the different abilities your tiles will have.
This choice will depend on what you want to do.
Bitset only
Oftentimes, the bitset-only variant is enough. To do that you'll need something along those lines:
You most probably want a set of flags which will represent different abilities of your tiles (e.g IsWalkable, IsWater, etc). Something similar to this:
struct TileFlag
{
bool m_IsWalkable : 1;
bool m_IsWater : 1;
//other flags you might need
};
With this in mind, your Tiles would be something along those lines (Texture and Texture manager are there just for the example):
struct Tile
{
void Render();
void Serialize(const boost::property_tree::ptree& tileData)
{
m_Flags.m_IsWalkable = tileData.get<bool>("walkable", false);
m_Flags.m_IsWater = tileData.get<bool>("water", false);
std::string texturePath = tileData.get<std::string>("texturePath", "");
m_TileTexture = TextureManager::GetOrLoad(texturePath);
}
TileFlags m_Flags;
std::shared_ptr<Texture> m_TileTexture;
};
You would need some kind of registry, where you contain all of your tiles, so that your levels can reference the tiles. This registry can be as simple as an std::map.
Some example code:
struct TileRegistry
{
void LoadTiles(const boost::property_tree::ptree& tiles)
{
for (boost::property_tree::ptree::value_type& tileType : tiles.get_child("tileTypes"))
{
std::unique_ptr<Tile> newTile = std::make_unique<Tile>();
newTile->Serialize(tileType.second);
m_Tiles[tileType.first] = std::move(newTile);
}
}
Tile* FindTile(const std::string& tileType)
{
Tile* result = nullptr;
auto search = m_Tiles.find(tileType);
if (search != m_Tiles.end()) {
result = search->second.get();
}
return result;
}
std::map<std::string, std::unique_ptr<Tile>> m_Tiles;
};
Then, when you load your levels, you just search for the Tile Type in the TileRegistry, and you'll get a pointer to your Tile.
OOP Style object inheritance
This approach would borrow a lot from the previous one, with the biggest difference being in how you are going to create your tiles. You are going to need some kind of Factory, as #artcorpse mentions.
If you want to go a bit more generic, you can do some automation magic with a few macros:
struct TileFactory
{
static std::map<std::string, CreateFunctionPtr> m_FactoryFunctors;
std::unique_ptr<ITile> CreateTile(const std::string& tileType)
{
std::unique_ptr<ITile> result;
auto search = m_FactoryFunctors.find(tileType);
if (search != m_FactoryFunctors.end()) {
auto creationFunctionPtr = search->second;
result = creationFunctionPtr(); //Notice the function invocation here
}
return result;
}
};
template<typename T>
struct TileRegistrator
{
TileRegistrator(const std::string& tileTypeName){
TileFactory::m_FactoryFunctors[tileTypeName] = &T::CreateTile;
}
};
#define DECLARE_TILE_TYPE(TileType) \
static std::unique_ptr<ITile> CreateTile() { return std::make_unique<TileType>();} \
static const TileRegistrator<TileType> s_Registrator;
#define DEFINE_TILE_TYPE(TileType) \
const TileRegistrator<TileType> TileType::s_Registrator = {#TileType};
And how you use those macros:
struct ITile
{
virtual ~ITile() = default; //Don't forget a virtual destructor when you have object which can be accessed by pointer to Base!
virtual bool IsWalkable() const = 0;
virtual bool IsSailable() const = 0;
virtual void Serialize(const boost::property_tree::ptree& tileData) = 0;
};
In your .h files, e.g. OceanTile.h:
struct OceanTile : public ITile
{
DECLARE_TILE_TYPE(OceanTile);
bool IsWalkable() const override;
bool IsSailable() const override;
void Serialize(const boost::property_tree::ptree& tileData) override;
int m_WavesIntensity{0};
};
In your .cpp files, e.g. OceanTile.cpp:
DEFINE_TILE_TYPE(OceanTile)
bool OceanTile::IsWalkable() const {
return false;
}
bool OceanTile::IsSailable() const {
return true;
}
void OceanTile::Serialize(const boost::property_tree::ptree& tileData) {
m_WavesIntensity = tileData.get<int>("WavesIntensity", 0);
}
And creating a new tile object, asuming you know its type as a string (e.g. coming from a data file is very simple:
void LoadTiles(const boost::property_tree::ptree& levelData)
{
for (boost::property_tree::ptree::value_type& tile : levelData.get_child("levelTiles"))
{
std::unique_ptr<ITile> newTile = TileFactory::CreateTile(tile->first);
newTile->Serialize(tile.second);
//Do whatever you want to do with your Tile - maybe store it in some vector of all tiles for the level or something
}
}
Disclaimer: I have not compiled or tested any of the above code, but hopefully it can give you an idea on how to get started. There might be any number of bugs hiding there.
I encourage you to start with the Bitset only option, as this is enough for a lot of different types of games, and is much simpler to work with and reason about.
Hope this gives you some start :)
I work on a project made with cocos2d-x framework (c++).
In my Player class, I have to manage the animations.
Iinitially I had this code that worked without any problem:
First, the animation object is a cocos2d Class cocos2d::Animation. Just remember that this object contains a cocos2d::Vector<AnimationFrame*> _frames; member.
Doc: http://www.cocos2d-x.org/reference/native-cpp/V3.5/d3/dc5/classcocos2d_1_1_animation.html#a0fdc0be158df7e09d04644be353db056
class Player : public cocos2d::Sprite {
private:
cocos2d::Map<std::string, cocos2d::Animation*> animations;
cocos2d::Vector<cocos2d::SpriteFrame*> getAnimation(const char *format, int frameStart, int count);
void update(float delta) override;
bool init() override;
public:
static Player* create();
bool init() override;
//...
};
And the implementation side:
bool Player::init() {
//...
animations.insert("idleN", Animation::createWithSpriteFrames(getAnimation("%04d", 207, 9), 0.1));
//...
}
Vector<SpriteFrame*> Player::getAnimation(const char *format, int frameStart, int count) {
auto spriteCache = SpriteFrameCache::getInstance();
Vector<SpriteFrame*> animFrames;
char str[100] = {0};
for (int i = 1; i <= count; i++)
{
sprintf(str, format, frameStart);
log("%s", str);
animFrames.pushBack(spriteCache->getSpriteFrameByName(str));
frameStart++;
}
return animFrames;
}
//later in the code execution
void Player::manageIdle() {
auto idleAnim = Animate::create(animations[0].anim);
runAction(idleAnim);
}
You can see each Animation is contained in cocos2d::Map<std::string, cocos2d::Animation*> and as I say before, this code worked perfectly, no error.
But I needed some more informations in addition to the name and the object itself so I decided to use a structure to store all infos for each animation. And I replaced the cocos2d::Map<std::string, cocos2d::Animation*> by std::vector<animData> with animData as structure. I refactored the code like so:
class Player : public cocos2d::Sprite {
public:
typedef struct animation {
std::string name;
cocos2d::Animation* anim;
//all others info needed, not relevant here, (just several enum type variables)
} animData;
private:
std::vector<animData > animations; //the new container
//rest of code stay unchanged
};
The changes in the implementation side:
bool Player::init() {
//...
animations.push_back({"idleN", Animation::createWithSpriteFrames(getAnimation("%04d", 207, 9), 0.1)});
//no problem here...
}
But now, when I try to create a new anim with a animation saved in my container (vector) I get a SegV on this line:
void Player::manageIdle() {
auto idleAnim = Animate::create(animations[0].anim); //SegV here, in Animate::create() funct
runAction(idleAnim);
}
After search, I find that each structure member anim which is type of cocos2d::Animation*, now conatains a empty cocos2d::Vector<AnimationFrame*> _frames; and there is the problem !
It’s as if they lose the cocos2d::Vector<AnimationFrame*> ref or something like that.
So my question is why cocos2d::Vector<AnimationFrame*> become empty with my refactored code and not whith the previous one ?
I found this with test like that:
auto test = animList[0].anim->getFrames();
if (test.empty()) {
log("empty"); //The test output empty
}
Debugguer screen in the end of the init() funct:
Debugguer screen in Player::manageIdle() funct:
Edit: when I add animations.back().anim->retain(); right after the line to add an element in the vector, it solves the problem !
animations.push_back({"idleN", Animation::createWithSpriteFrames(getAnimation("%04d", 207, 9), 0.1)});
animations.back().anim->retain();
Because cocos2d::Animation* inherit from cocos2d::Ref, it is an auto-release object. When used inside a cocos2d container like cocos2d::Map or cocos2d::Vector, it is auto managed by the container itself. But I use a std::vector so I lose the ref I think. Something like that.
Now I need to find a way to get rid of this additional line of code because this multiple by twice my number of line here !
So new question here: How I can get rid of the fact I have to call animations.back().anim->retain(); each time I add a new element in my vector ?
You might create a wrapper around Ref, which "retains" ownership, and store this wrapper instead, sort of a std::unique_ptr e.g.
template<typename T> class RefOwner {
public:
RefOwner(T *t) : ref(t) {
ref->retain();
}
~RefOwner() {
ref->release();
}
T *operator->() { return ref; }
private:
T *ref;
};
and then use it as
struct animData {
std::string name;
RefOwner<cocos2d::Animation> anim;
//all others info needed, not relevant here, (just several enum type variables)
};
Disclaimer: I have no experience with cocos2d-x, just looked at Animation and Ref
I asked a question yesterday, but it seems I did ask it incorrectly, so here I go again. I quickly mocked up this code, and I'm wondering if this is a proper way to handle the objects (outside of just putting everything in main(). This would be my first time trying to complete a larger project, so I've never had a need to question how to contain and handle the objects.
skill.h
#pragma once
#include <string>
#include <vector>
#include <memory>
#include <unordered_map>
class Skill;
typedef std::vector<std::shared_ptr<Skill>> SkillVector;
typedef std::unordered_map<std::string, std::shared_ptr<Skill>> SkillMap;
class Skill {
private:
std::string _skill_name;
std::string _skill_description;
friend std::ostream& operator<< (std::ostream& stream, const Skill& skill);
void print(std::ostream& stream) const;
public:
Skill(const std::string& skill_name, const std::string& skill_description);
const std::string& getSkillName() const;
const std::string& getSkillDescription() const;
bool isMatch(const std::string& substring) const;
};
application.h
#pragma once
#include "skill.h"
extern std::string SKILL_FILE;
class Application {
private:
std::unique_ptr<SkillMap> _skill_map;
void loadData();
void loadSkills();
void printSkillMap();
void printSkillVector(const SkillVector& skills);
std::unique_ptr<SkillVector> skillSearch(const std::string& input) const;
public:
Application();
void run();
};
main.cpp
#include "application.h"
int main() {
std::unique_ptr<Application> application(new Application);
application->run();
return 0;
}
This is going to be a command-line application, so other than this I can't think of doing anything else except putting all the methods from the application class straight into main as regular functions. That doesn't seem like the correct approach though. I've tried researching this pretty extensively, but haven't really found anything that answers this.
What are the other options for containing all the objects in an orderly fashion? What are the advantages of doing it certain ways? And is what I'm doing here acceptable?
NOTE: This isn't an exact representation of my project, and I'm just using it as an example to understand my question at hand.
TL;DR There isn't a single answer on how to move forward. It depends on:
What your goal is.
What subsystems the project will have, and how they integrate with one another.
The type and quantity of data that the project will require.
That said, it's almost always a good idea to apply separation of concerns, segregating data & functionality between types that correspond to each of your project's concerns. Here's an example using a finite state machine to get you started:
// Note that this example uses C++11 features.
// Note that the stubs are intentional, to keep this example as terse as possible.
// For consistency with your naming style.
typedef std::string String;
template<typename T>
using Vector = std::vector<T>;
template<typename T>
using UniquePtr = std::unique_ptr<T>;
// Skill.hpp: Represents a single skill.
class Skill {
private:
String _name;
String _description;
public:
Skill(String name, String description);
const String& getName() const { return _name; }
const String& getDescription() const { return _description; }
};
// Player.hpp: Represents a single player.
class Player {
private:
Vector<Skill*> _skills;
bool _isVirtual; // Is this player from another computer? (networked multiplayer)
public:
Player(bool isVirtual = false) :
_skills(),
_isVirtual(isVirtual) {}
Player(const Player& other) = delete; // Non-copyable.
bool hasSkill(Skill* skill) const;
void addSkill(Skill* skill);
bool removeSkill(Skill* skill); // Returns true if removed, false otherwise.
bool isVirtual() const { return _isVirtual; }
};
// Level.hpp: Represents a single level of the game.
class Level {
private:
// Per-level data...
public:
Level();
Level(const Level& other) = delete; // Non-copyable.
};
// GameState.hpp: Represents the state of the game.
enum class GameState {
MainMenu, // The user is in the main menu.
World, // The user is navigating the world.
Combat, // The user is in combat.
};
// Game.hpp: Represents a single game instance.
class Game {
private:
Application* _app;
Vector<UniquePtr<Player>> _players;
Vector<UniquePtr<Level>> _levels;
Level* _level; // Current level the player(s) are on.
GameState _state; // Current state of the game.
bool _isRunning; // Is the game running?
void mainMenuLoop() {
while (_isRunning) {
// Implement your main menu here.
// Update the menu display after user input.
// When a selection is confirmed, execute it and return.
}
}
void combatLoop() {
while (_isRunning) {
// Implement your combat system here.
// When combat is over, update _state and return.
}
}
public:
Game(Application* app) :
_app(app),
_players(),
_levels(),
_level(),
_state(GameState::MainMenu),
_isRunning(true) {
// Finish initializing and:
// If loading is fast enough, do so here.
// If loading is slow, spin up a thread and load asynchronously.
}
Game(const Game& other) = delete; // Non-copyable.
void run() {
// If loading is slow, wait on the loading thread to complete.
// Possibly show an introduction banner.
while (_isRunning) {
switch (_state) {
case GameState::MainMenu:
mainMenuLoop();
break;
case GameState::Combat:
combatLoop();
break;
}
}
}
void quit() { _isRunning = false; }
const Player* getPlayer(int index) const;
Player* getPlayer(int index);
void addPlayer(Player* player);
bool removePlayer(Player* player); // Returns true if removed, false otherwise.
const Level* getLevel(int index) const;
Level* getLevel(int index);
void addLevel(Level* level);
bool removeLevel(Level* level); // Returns true if removed, false otherwise.
};
// Options.hpp: Represents command line options.
struct Options {
// Add your command line options here.
Options();
Options(const Options& other);
};
// Application.hpp: Represents a single application instance.
class Application {
private:
Options _options;
Game _game;
public:
// For compatibility with your code.
Application() :
_options(),
_game(this) {}
// For later, when you add command line options.
Application(const Options& options) :
_options(options),
_game(this) {}
Application(const Application& other) = delete; // Non-copyable.
const Options& getOptions() const { return _options; }
const Game* getGame() const { return &_game; }
Game* getGame() { return &_game; }
// For compatibility with your code. You could
// remove this and directly use getGame()->run()
void run() { _game.run(); }
};
In main using unique_ptr for the Application object is unnecessary. Use the stack instead:
// Added arguments because you'll probably want command-line options later.
int main(int argc, char** argv) {
Application app; // Better locality, no dynamic allocation.
app.run();
return 0;
}
Follow the following rules:
When you have inheritance, the classes should respond to 'is-a'. For example if you have class Speed : public Skill. That seems logical and: Speed is a Skill.
When you have composition, the classes should respond to 'has-a'. In your case: Application has a Skill map.
If the class was Hero it would be really logical: Hero has a Skill map. And this hero will develop the skills also the hero might need to print its skills... So the Hero will manage his Skills.
Sorry if I misunderstood your question.
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).
I have class called "UltrasoundTemplate". These UltrasoundTemplate objects contain an int parameter, which shows when they where defined (something like a time stamp). And I have a class called "UltrasoundTarget" which contains a vector of UltrasoundTemplate's.
I add UltrasoundTemplates to the vector with push_back(ultrasoundTemplate).
Now I want to sort the vector by the order of time stamps instead of the order I added them to the vector.
I found a lot of answers in google, which all show me the same solution, but obviously I'm still doing something wrong. Here are the code snippets I think are necessary for finding a solution:
ultrasoundTemplate.h
class UltrasoundTemplate
{
public:
UltrasoundTemplate(/*...*/);
int getVolumePos() { return volume_; }
private:
int volume_;
};
ultrasoundTarget.h
//the sort algorithm
struct MyTemplateSort {
bool operator() ( UltrasoundTemplate t1, UltrasoundTemplate t2){
int it1 = t1.getVolumePos();
int it2 = t2.getVolumePos();
if (it1 < it2)
return true;
return false;
}
};
class UltrasoundTarget
{
public:
UltrasoundTarget(/*...*/);
vector<UltrasoundTemplate> getTemplates() { return USTemplateVector_; }
private:
vector<UltrasoundTemplate> USTemplateVector_;
};
FMainWindow.cpp
void FMainWindow::match_slot()
{
int i;
//here I get the name of the target I'm looking for
QTreeWidgetItem *item = targetInfoWidget_->treeWidget->currentItem();
int index = targetInfoWidget_->treeWidget->indexOfTopLevelItem(item);
QString itemToAppendName = item->text(0);
for(i = 0; i < USTargetVector.size(); i++){
if(USTargetVector.at(i).getName() == itemToAppendName) {
//here I try to sort
MyTemplateSort tmpltSrt;
std::sort(USTargetVector.at(i).getTemplates().begin(),
USTargetVector.at(i).getTemplates().end(), tmpltSrt);
break;
}
}
As an example: I define Template1 in Volume(0), Template2 in Volume(70) and Template3 in Volume(40). The order now is (Template1, Template2, Template3) but I want it to be (Template1, Template3, Template2). But this code is not doing it.
If there's Information missing, just tell me and I'll provide more code.
Thanks alot.
Your getTemplates() method returns by value, making a mess here:
std::sort(USTargetVector.at(i).getTemplates().begin(),
USTargetVector.at(i).getTemplates().end(), tmpltSrt);
You are sorting an incompatible iterator range. You can fix that particular problem by returning a reference:
vector<UltrasoundTemplate>& getTemplates() { return USTemplateVector_; }
It is common practice to add a const overload to such a method:
const vector<UltrasoundTemplate>& getTemplates() const { return USTemplateVector_; }
You can also modify your comparison functor to avoid unnecessary copies (and for general readability and const correctness):
struct MyTemplateSort {
bool operator() const ( const UltrasoundTemplate& t1, const UltrasoundTemplate& t2)
{
return t1.getVolumePos() < t2.getVolumePos();
}
};
This will require that you make getVolumePos() a const method, which it should be anyway:
class UltrasoundTemplate
{
public:
...
int getVolumePos() const { return volume_; }
...
};
Note that is is not generally good practice to provide references to the private data of a class. If possible, you should find a way to remove that from the UltraSoundTarget interface. You could, for instance, expose a pair of iterators, and/or give the class a sort method.
juanchopanza answer is correct, the problem is the way you are returning the vector from UltrasoundTarget. Just to touch another topic, maybe it would be nice to change a little the designing of your implementation. As UltrasoundTarget is a container of Ultrasound's, it makes sense to implement the sort as a method of this class, this way you have direct access to USTemplateVector_ and will save unecessary copies. Something like:
class UltrasoundTarget
{
public:
UltrasoundTarget(/*...*/);
vector<UltrasoundTemplate> getTemplates() { return USTemplateVector_; }
void sort();
private:
vector<UltrasoundTemplate> USTemplateVector_;
};
void UltrasoundTarget::sort()
{
std::sort(USTemplateVector_.begin(), USTemplateVector_.end(), tmpltSrt);
}
void FMainWindow::match_slot()
{
int i;
//here I get the name of the target I'm looking for
QTreeWidgetItem *item = targetInfoWidget_->treeWidget->currentItem();
int index = targetInfoWidget_->treeWidget->indexOfTopLevelItem(item);
QString itemToAppendName = item->text(0);
for(i = 0; i < USTargetVector.size(); i++){
if(USTargetVector.at(i).getName() == itemToAppendName)
{
//here I try to sort
MyTemplateSort tmpltSrt;
USTargetVector.at(i).sort();
break;
}
}