I try to to call a method but it crashes when it trys to access a QMap member variable of AbstractIpCalculator.
I am calling like this:
AbstractIpCalculator *calculator = item_group.at(i).getCalculator();
calculator->setId(1, net_ids[1]);
ABSTRACTIPCALCULATOR_H:
#ifndef ABSTRACTIPCALCULATOR_H
#define ABSTRACTIPCALCULATOR_H
#include <QString>
#include <QDebug>
#include <QPair>
#include <QQueue>
class AbstractIpCalculator
{
public:
AbstractIpCalculator();
...
bool setId(int index, double value);
virtual QString calculate(QString) = 0;
protected:
QMap<int, double> park_netz_list;
...
private:
virtual QString calculateOctetOne(QString) = 0;
virtual QString calculateOctetTwo(QString) = 0;
virtual QString calculateOctetThree(QString) = 0;
virtual QString calculateOctetFour(QString) = 0;
};
#endif // ABSTRACTIPCALCULATOR_H
The method setParkNetzId:
bool AbstractIpCalculator::setId(int index, double value)
{
if(index >= 1)
{
qDebug() << index << value << " " << (&park_netz_list == nullptr);
park_netz_list.insert(index, value); // <--- crash!!!
return true;
}
return false;
}
There are many subclasses which extend AbstractIpCalculator. *calculator is a derived class but at this point I don't know which.
My debugger says : read access violation at: 0x0, flags=0x0 (first chance) and stops in qmap.h line 73.
I am using Qt 5.0.2.
Thank you in advance!
EDIT:
Is maybe something wrong with the setCalculator or getCalculator method?
AbstractIpCalculator *CalculatorItemGroup::getCalculator() const
{
return calculator_item;
}
void CalculatorItemGroup::setCalculator(AbstractIpCalculator &calculator_item)
{
this->calculator_item = &calculator_item;
}
initialization:
CalculatorItemGroup item;
item..setCalculator(c);
Related
I have several singleton classes. Two of them each run as a separate thread. In one class, two vectors are filled and that works. If I now call the getPlayersEnemy function in the other class, the vector is always empty and I don't know why.
Player-Class:
#pragma once
#include <cstdint>
#include <string>
#include "Structs.h"
#include <vector>
class Player
{
private:
Player() {}
std::vector<entity> playersTeam;
std::vector<entity> playersEnemy;
int local = 0;
public:
static Player& getInstance()
{
static Player instance;
return instance;
}
void obtainPlayers();
std::vector<entity> getPlayersTeam();
std::vector<entity> getPlayersEnemy();
};
The two get*-Functions:
std::vector<entity> Player::getPlayersTeam()
{
return playersTeam;
}
std::vector<entity> Player::getPlayersEnemy()
{
return playersEnemy;
}
In the obtainPlayers function the vectors are getting filled(and also this is the function which runs in a thread)
Now, in the Categroize-Class, I init the Player class and call getPlayersTeam()/getPlayersEnemy():
#pragma once
#include "Game.h"
#include "Player.h"
class Categorize
{
private:
Categorize() {}
Memory& mem = Memory::getInstance();
Player& player = Player::getInstance();
Game& game = Game::getInstance();
public:
static Categorize & getInstance()
{
static Categorize instance;
return instance;
}
void run();
};
void Categorize::run()
{
while (true)
{
if (game.isFullyLoaded())
{
if (player.getPlayersEnemy().empty())
{
std::cout << "empty vector" << std::endl;
}
for (const entity ent : player.getPlayersEnemy())
{
std::cout << "called" << std::endl;
}
}
}
}
Here is where they're getting filled:
void Player::obtainPlayers()
{
while (true)
{
playersTeam.clear();
playersEnemy.clear();
Entity& ent = Entity::getInstance();
int localPlayer = ent.getLocalplayer();
if (!localPlayer)
{
continue;
}
std::cout << ent.getHealth(localPlayer);
playersTeam.push_back(
entity
{
localPlayer,
ent.getHealth(localPlayer),
true,
true,
true,
ent.getPosition(localPlayer)
}
);
int localPlayerTeam = ent.getTeam(localPlayer);
int team = 1;
int enemy = 0;
for (int i = 1; i < 64; i++)
{
int player = ent.getEntityByIndex(i);
if (player == localPlayer || !player)
{
continue;
}
if (ent.getTeam(player) == localPlayerTeam)
{
playersTeam.push_back(
entity{
player,
ent.getHealth(player),
ent.isDormant(player),
ent.isVisible(player, localPlayer),
ent.isSpotted(player),
ent.getPosition(player)
}
);
}
else
{
playersEnemy.push_back(
entity{
player,
ent.getHealth(player),
ent.isDormant(player),
ent.isVisible(player, localPlayer),
ent.isSpotted(player),
ent.getPosition(player)
}
);
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
}
Also the Categorize::run() is also running in another thread.
I don't know why the return of getPlayersEnemy()/getPlayersTeam() is always empty, where it is not, when I check in the player-class itslef.
I'm recently learning to make a 2d game in SFML using a tutorial series on youtube by Suraj Sharma(Video 57):
https://www.youtube.com/watch?v=kwd_AVCkvXE&list=PL6xSOsbVA1ebkU66okpi-KViAO8_9DJKg&index=57
His Source Code:
https://github.com/Headturna/SFML_RPG
Right now he's teaching me to symplify the game's menu system by making a mini class 'StateData' in the parent class 'State' so any inherited class can access 'State' parameters via 'StateData'(Ex:MainMenu(StData* Stdata){}).
After debugging the game seems to runs fine.But everytime i click on something on the menu(start,settings,etc...) a 'Read access violation:Stdata was nullptr' occurs in the 'State' class constructor.
Here's the code:
State.h:
#pragma once
#ifndef STATE_H
#define STATE_H
#include "Player.h"
#include "GrphSettings.h"
class Player;
class GrphSettings;
class State;
class StData {
public:
StData(){}
//Vars
float GridSize;
sf::RenderWindow* Window;
GrphSettings* GSettings;
std::map<std::string, int>* SupportedKeys;
std::stack<State*>* states;
};
class State
{
private:
protected:
StData* Stdata;
std::stack<State*>* states;
sf::RenderWindow* window;
std::map<std::string, int>* SupportedKeys ;
std::map<std::string, int> Keybinds;
bool quit;
bool pause;
float keyTime;
float keyTimeMax;
float GridSize;
sf::Vector2i MousePosScr;
sf::Vector2i MousePosWind;
sf::Vector2f MousePosView;
//Resources
std::map<std::string,sf::Texture> texture;
//Funcs
virtual void InitKeybinds() = 0;
public:
State(StData* Stdata);
virtual~State();
//Access
const bool getKeytime();
const bool& getquit()const;
//Funcs
void Endstate();
void PauseSt();
void UnPauseSt();
virtual void UpdateInput(const float& dt) = 0;
virtual void UpdateMousePos();
virtual void UpdateKeyTime(const float& dt);
virtual void Update(const float& dt) = 0;
virtual void Render(sf::RenderTarget* target = nullptr) = 0;
};
#endif // !1
State.cpp:
#include "pch.h"
#include "State.h"
State::State(StData* Stdata)
{
this->Stdata = Stdata;
this->window = Stdata->Window;
this->SupportedKeys = Stdata->SupportedKeys;
this->states = Stdata->states;
this->quit = false;
this->pause = false;
this->keyTime = 0.f;
this->keyTimeMax = 10.f;
this->GridSize = Stdata->GridSize;
}
State::~State()
{
}
//Access
const bool State::getKeytime()
{
if (this->keyTime >= this->keyTimeMax) {
this->keyTime = 0.f;
return true;
}
return false;
}
const bool& State::getquit() const
{
// TODO: insert return statement here
return this->quit;
}
//Funcs
void State::Endstate()
{
this->quit = true;
}
void State::PauseSt()
{
this->pause = true;
}
void State::UnPauseSt()
{
this->pause = false;
}
void State::UpdateMousePos()
{
this->MousePosScr = sf::Mouse::getPosition();
this->MousePosWind = sf::Mouse::getPosition(*this->window);
this->MousePosView = this->window->mapPixelToCoords(sf::Mouse::getPosition(*this->window));
}
void State::UpdateKeyTime(const float& dt)
{
if (this->keyTime < this->keyTimeMax)
this->keyTime += 100.f * dt;
}
Every button one the menu(start,exit...)is an inherited state from 'State' class.This is,for example,the 'Edit' state.
Edit.h:
#pragma once
#ifndef EDIT_H
#define EDIT_H
#include "State.h"
#include "Gui.h"
#include "PauseMenu.h"
#include "TileMap.h"
class State;
class Gui;
class PauseMenu;
class TileMap;
class Edit:public State
{
private:
//Vars
sf::Font Fnt;
PauseMenu* PMenu;
std::map<std::string, gui::Button*> buttons;
TileMap Map;
//Functions
void InitVars();
void InitBackGrnd();
void InitFonts();
void InitKeybinds();
void InitPauseMenu();
void InitBtn();
public:
Edit(StData* Stdata);
virtual~Edit();
//Functions
void UpdateInput(const float& dt);
void Update(const float& dt);
void UpdatePButtons();
void UpdateBtn();
void Endstate();
void RenderBtn(sf::RenderTarget& target);
void Render(sf::RenderTarget* target = nullptr);
};
#endif // ! EDIT_H
Edit.cpp:
#include "pch.h"
#include "Edit.h"
void Edit::InitVars()
{
}
void Edit::InitBackGrnd()
{
}
void Edit::InitFonts()
{
if (!this->Fnt.loadFromFile("Fonts/SPACEMAN.ttf")) {
throw("Error::Edit::Couldn't load font");
}
}
void Edit::InitKeybinds()
{
std::ifstream ifs("Config/EditKeys.ini");
if (ifs.is_open()) {
std::string key = "";
std::string key2 = "";
int keyval = 0;
while (ifs >> key >> key2)
{
this->Keybinds[key] = this->SupportedKeys->at(key2);
}
}
ifs.close();
this->Keybinds["Close"] = this->SupportedKeys->at("ESC");
this->Keybinds["Left"] = this->SupportedKeys->at("A");
this->Keybinds["Right"] = this->SupportedKeys->at("D");
this->Keybinds["Up"] = this->SupportedKeys->at("W");
this->Keybinds["Down"] = this->SupportedKeys->at("S");
}
void Edit::InitPauseMenu()
{
this->PMenu = new PauseMenu(*this->window, this->Fnt);
this->PMenu->addButtons("Quit", 800.f, "Quit");
}
void Edit::InitBtn()
{
}
Edit::Edit(StData* Stdata)
:State(Stdata)
{
this->InitVars();
this->InitBackGrnd();
this->InitFonts();
this->InitKeybinds();
this->InitPauseMenu();
this->InitBtn();
}
Edit::~Edit()
{
auto it = this->buttons.begin();
for (it = this->buttons.begin(); it != this->buttons.end(); ++it) {
delete it->second;
}
delete this->PMenu;
}
//Funcs
void Edit::UpdateInput(const float& dt)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Key(this->Keybinds.at("Close")))
&& this->getKeytime()) {
if (!this->pause)
this->PauseSt();
else this->UnPauseSt();
}
}
void Edit::Update(const float& dt)
{
this->UpdateMousePos();
this->UpdateKeyTime(dt);
this->UpdateInput(dt);
if (!this->pause) {//Unpaused
this->UpdateBtn();
}
else {//Paused
this->PMenu->Update(this->MousePosView);
this->UpdatePButtons();
}
this->UpdateBtn();
std::cout << this->MousePosView.x << " " << this->MousePosView.y << "\r";
}
void Edit::UpdatePButtons()
{
if (this->PMenu->isPressed("Quit"))
this->Endstate();
}
void Edit::UpdateBtn()
{ //Update buttons and handle their functions
for (auto& it : this->buttons) {
it.second->Update(MousePosView);
}
}
void Edit::Endstate()
{
std::cout << "Ending State" << "\n";
}
void Edit::RenderBtn(sf::RenderTarget& target)
{
for (auto& it : this->buttons) {
it.second->Render(target);
}
}
void Edit::Render(sf::RenderTarget* target)
{
if (!target)
target = this->window;
this->RenderBtn(*target);
this->Map.Render(*target);
if (this->pause) {//Pause Menu
this->PMenu->Render(*target);
}
sf::Text MText;
MText.setPosition(this->MousePosView);
MText.setFont(this->Fnt);
MText.setCharacterSize(12);
std::stringstream ss;
ss << this->MousePosView.x << ' ' << this->MousePosView.y;
MText.setString(ss.str());
target->draw(MText);
}
Can anyone help me ?
How to run a function of an actual object, which is stored in the container using OOP?
Background: I'm writing a game. There is a set of 4 interconnected rooms. There are two different room types and two different player types. Players should run as threads. The Killer should have a fight with a normal player in the Action room. In the second type of room, nothing should happen. The game logic and code is simplified.
When the thread starts, void Player::operator()() is being executed. The player enters the room, does his action initializeAction(), and leaves it. In case of a Killer, his initializeAction() leads to room->actionInRoom(*this), which executes player.inActionRoom().
The problem is in this code void Killer::inActionRoom():
std::vector<Player> &playersWithoutKillers = room->getPlayersWithoutKillers();
auto it = playersWithoutKillers.begin();
std::advance(it, 0);
Player chosenPlayerForFight = *it;
...
chosenPlayerForFight.decreasePoints();
where chosenPlayerForFight.decreasePoints(); does not decrease the points for the actual player, but I think it does it for a copy of an object.
If I run the code, this mistake is visible: OtherPlayer's points will always reset to 1. If I'm decreasing it every time the fight occurs, the negative value is expected.
-> Killer in Forth room Killer 11 vs OtherPlayer 1
Starting decreasing points from 1
Ending decreasing points from 0
I tried to fix the code, mainly by making sure the reference of an object is passed.
Main.cpp:
#include <iostream>
#include <memory>
#include <thread>
#include "Room.h"
#include "Player.h"
std::mutex globalMessageMutex;
int main() {
auto first = std::make_shared<RelaxRoom>("First room");
auto second = std::make_shared<ActionRoom>("Second room");
auto third = std::make_shared<RelaxRoom>("Third room");
auto forth = std::make_shared<ActionRoom>("Forth room");
first->setRoomPair(second, forth);
second->setRoomPair(third, first);
third->setRoomPair(forth, second);
forth->setRoomPair(first, third);
std::vector<std::thread> players;
players.emplace_back(OtherPlayer("OtherPlayer", first));
players.emplace_back(Killer("Killer", first));
for (auto &t : players) {
if (t.joinable()) {
t.join();
}
}
return 0;
}
Player.h
#ifndef HW03_PLAYER_H
#define HW03_PLAYER_H
#include <string>
#include <memory>
class Room;
class Player {
friend class Room;
public:
Player(const std::string &playerName, std::shared_ptr<Room> initialTargetRoom);
void operator()();
friend bool operator== ( const Player &lhs, const Player &rhs );
const std::string &getName() const;
virtual void inActionRoom() {};
virtual void inRelaxRoom(Room &pRoom) {};
virtual bool isKiller()const;
virtual bool isOtherPlayer();
int getPoints()const;
void increasePoints();
void decreasePoints();
int points;
protected:
std::shared_ptr<Room> room;
virtual void initializeAction();
private:
std::string name;
std::shared_ptr<Room> initialRoom;
};
class OtherPlayer : public Player {
public:
OtherPlayer(const std::string &playerName, const std::shared_ptr<Room> &initialTargetRoom);
void initializeAction() override;
void inActionRoom() override;
void inRelaxRoom(Room &pRoom) override;
bool isOtherPlayer() override;
};
class Killer : public Player {
public:
Killer(const std::string &playerName, const std::shared_ptr<Room> &initialTargetRoom);
void initializeAction() override;
void inActionRoom() override;
void inRelaxRoom(Room &pRoom) override;
bool isKiller() const override;
};
#endif //HW03_PLAYER_H
Player.cpp
#include <iostream>
#include <chrono>
#include <thread>
#include <random>
#include "Player.h"
#include "Room.h"
extern std::mutex globalMessageMutex;
Player::Player(const std::string &playerName, std::shared_ptr<Room> initialTargetRoom) {
name = playerName;
initialRoom = initialTargetRoom;
room = initialTargetRoom;
points = 1;
}
void Player::operator()() {
room->enter(*this);
initializeAction();
std::this_thread::sleep_for(std::chrono::milliseconds(20));
room->leave(*this);
while (auto nextRoom = room->getNext()) {
room = nextRoom;
nextRoom->enter(*this);
initializeAction();
std::this_thread::sleep_for(std::chrono::milliseconds(20));
nextRoom->leave(*this);
}
}
void Player::initializeAction() {}
bool operator==(const Player &lhs, const Player &rhs) {
return lhs.name == rhs.name;
}
const std::string &Player::getName() const {
return name;
}
bool Player::isKiller() const {
return false;
}
bool Player::isOtherPlayer() {
return false;
}
int Player::getPoints() const {
return points;
}
void Player::increasePoints() {
points++;
}
void Player::decreasePoints() {
std::cout << "Starting decreasing points from " << points << std::endl;
points--;
std::cout << "Ending decreasing points from " << points << std::endl;
}
OtherPlayer::OtherPlayer(const std::string &playerName, const std::shared_ptr<Room> &initialTargetRoom) : Player(playerName,
initialTargetRoom) {}
void OtherPlayer::initializeAction() {
room->actionInRoom(*this);
}
void OtherPlayer::inActionRoom() {}
void OtherPlayer::inRelaxRoom(Room &pRoom) {}
bool OtherPlayer::isOtherPlayer() {
return true;
}
Killer::Killer(const std::string &playerName, const std::shared_ptr<Room> &initialTargetRoom) : Player(playerName,
initialTargetRoom) {}
void Killer::initializeAction() {
room->actionInRoom(*this);
}
void Killer::inActionRoom() {
std::lock_guard<std::mutex> ml(globalMessageMutex);
if (!room->getPlayersWithoutKillers().empty()) {
**std::vector<Player> &playersWithoutKillers = room->getPlayersWithoutKillers();**
**auto it = playersWithoutKillers.begin();
std::advance(it, 0);
Player chosenPlayerForFight = *it;**
auto killersVitality = this->getPoints();
auto othersPlayerPoints = chosenPlayerForFight.getPoints();
std::cout << "-> Killer in " << room->getName() << " " << this->getName() << " " << killersVitality
<< " vs " << chosenPlayerForFight.getName() << " " << othersPlayerPoints << std::endl;
this->increasePoints();
**chosenPlayerForFight.decreasePoints();**
}
}
void Killer::inRelaxRoom(Room &pRoom) {
}
bool Killer::isKiller() const {
return true;
}
Room.h
#ifndef HW03_ROOM_H
#define HW03_ROOM_H
#include <string>
#include <vector>
#include <condition_variable>
class Player;
class Room {
public:
Room(const std::string &roomName);
void setRoomPair(std::shared_ptr<Room> firstRoom, std::shared_ptr<Room> secondRoom);
std::shared_ptr<Room> getNext();
void enter(Player &player);
void leave(Player &player);
virtual void actionInRoom(Player &player)= 0;
const std::string &getName() const;
const std::vector<Player> &getPlayers();
std::vector<Player> &getPlayersWithoutKillers();
protected:
std::string name;
size_t killersCount;
size_t playersWithoutKillersCount;
private:
std::vector<Player> players;
std::vector<Player> playersWithoutKillers;
std::condition_variable cv;
std::mutex mutex;
std::pair<std::shared_ptr<Room>, std::shared_ptr<Room>> roomPair;
void updateCounterPlayerLeaves(Player &player);
void updateCounterPlayerEnters(Player &player);
};
class ActionRoom : public Room {
public:
ActionRoom(const std::string &roomName) : Room(roomName) {}
void actionInRoom(Player &player) override;
};
class RelaxRoom : public Room {
public:
RelaxRoom(const std::string &roomName) : Room(roomName) {}
void actionInRoom(Player &player) override;
};
#endif //HW03_ROOM_H
Room.cpp
#include <iostream>
#include <algorithm>
#include <random>
#include "Room.h"
#include "Player.h"
#include <mutex>
extern std::mutex globalMessageMutex;
Room::Room(const std::string &roomName) {
name = roomName;
}
const std::string &Room::getName() const {
return name;
}
std::shared_ptr<Room> Room::getNext() {
auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
std::mt19937 engine(seed);
std::uniform_int_distribution<int> randomGenerator(0, 1);
auto randomNumber = randomGenerator(engine);
if (randomNumber) {
return roomPair.second;
}
return roomPair.first;
}
void Room::enter(Player &player) {
std::unique_lock<std::mutex> lock(mutex);
cv.wait(lock, [this, &player] {
return true;
}
);
players.push_back(player);
updateCounterPlayerEnters(player);
std::lock_guard<std::mutex> ml(globalMessageMutex);
std::cout << name << ": killers: " << killersCount << ", other players: " << playersWithoutKillersCount <<
std::endl;
}
void Room::updateCounterPlayerEnters(Player &player) {
if (player.isKiller()) {
killersCount++;
} else {
playersWithoutKillersCount++;
playersWithoutKillers.push_back(player);
}
}
void Room::leave(Player &player) {
{
std::lock_guard<std::mutex> lock(mutex);
auto it = std::find(players.begin(), players.end(), player);
if (it == players.end()) {
return;
}
players.erase(it);
updateCounterPlayerLeaves(player);
}
cv.notify_all();
}
void Room::updateCounterPlayerLeaves(Player &player) {
if (player.isKiller()) {
killersCount--;
} else {
playersWithoutKillersCount--;
auto it = std::find(playersWithoutKillers.begin(), playersWithoutKillers.end(), player);
if (it == playersWithoutKillers.end()) {
return;
}
playersWithoutKillers.erase(it);
}
}
void Room::setRoomPair(std::shared_ptr<Room> firstRoom, std::shared_ptr<Room> secondRoom) {
roomPair.first = std::move(firstRoom);
roomPair.second = std::move(secondRoom);
}
const std::vector<Player> &Room::getPlayers() {
return players;
}
std::vector<Player> &Room::getPlayersWithoutKillers() {
return playersWithoutKillers;
}
void ActionRoom::actionInRoom(Player &player) {
player.inActionRoom();
}
void RelaxRoom::actionInRoom(Player &player) {
player.inRelaxRoom(*this);
}
Not a complete answer, since you said this is a homework assignment.
However, one pattern you can use to solve this problem is to have your container store std::unique_ptr<some_base_class> values, or if necessary std::shared_ptr<some_base_class>, and fill them with pointers to derived objects. For example: container.emplace_back(static_cast<some_base_class*>(new derived_class(foo, bar, baz))); will construct everything in place inside your container, so the compiler doesn’t need to make any temporary copies. You might also write something like:
std::vector<std::unique_ptr<some_base_class>> container;
{
std::unique_ptr<derived_class> temp =
make_unique<derived_class>();
temp->setup( foo, bar, baz );
container.emplace_back(static_cast<some_base_class*>(temp.release()));
// temp is now empty, and the pointer in the container now owns the object.
}
You can use the full interface of some_base_class through these smart pointers, with ->, but if you need to turn them back into references to derived objects, you would use RTTI and dynamic_cast.
There are other approaches, including a discriminated union and std::variant, but storing smart pointers to the base class that defines your interface is what I recommend you try here.
I first get an object A from the vector, then I call the erase method to destroy that object in my vector because I don't need it anymore. However, from the debugger, I found that the object A I got before calling erase method is also destroyed. I don't understand that because I thought that what I got is a copy of that object and erase method should have nothing to do with my object A.
Code
Class Unit
Header file
#ifndef UNIT_H
#define UNIT_H
#include <iostream>
class Unit
{
protected:
int id;
public:
Unit::Unit(int num = -1);
virtual ~Unit() = default;
virtual int getID();
};
#endif
CPP file
#include "Unit.h"
Unit::Unit(int num)
{
id = num;
}
int Unit::getID()
{
return id;
}
Class Box
Header file
#ifndef BOX_H
#define BOX_H
#include <string>
#include <iostream>
#include "Unit.h"
class Box : public Unit
{
private:
std::string* type;
int* val;
public:
Box::Box();
~Box();
int getVal();
std::string getName();
int getID() override;
};
#endif
CPP file
#include <time.h>
#include "Box.h"
Box::Box() : Unit(5)
{
int tmp = rand() % 3;
if (tmp == 0)
{
type = new std::string("hp"); // health cur
val = new int(rand() % 10 + 1);
}
else if (tmp == 1)
{
type = new std::string("exp"); // skill level or health max
val = new int(rand() % 5 + 1);
}
else
{
type = new std::string("punish"); // minus health cur
val = new int(-1);
}
}
Box::~Box()
{
delete type;
delete val;
}
int Box::getVal()
{
return *val;
}
std::string Box::getName()
{
return *type;
}
int Box::getID()
{
return id;
}
main file
using namespace std;
int main()
{
Box test;
std::vector<Box> bag;
bag.push_back(test);
Box tmp = bag[0];
bag.erase(bag.begin() + 0);
cout << tmp.getVal();
system("pause");
return 0;
}
Below is the screenshot from the debugger and because I don't have 10 reputations, I can't display it directly.
before
after
As you can see, the "type" and "val" data member of class Box is modified.
Check out this page about the return type from the index call
http://en.cppreference.com/w/cpp/container/vector/operator_at
I believe that you may have a reference, not a different object.
I am trying to save 3 QVector<QPoint> and an int with QDataStream.
I overloaded the operator<<(), but if I try to save something, nothing appears in the file.
I checked if the QVector is empty, but it wasn't.
So here is the CloudData class with the operator<< and save() function:
CloudData.h
#include <QDataStream>
#include <QVector>
#include <QPoint>
class CloudData
{
public:
CloudData();
QVector<QPoint> getPolyVector() const;
QVector<QPoint> getPathPointVector() const;
QVector<QPoint> getSupPointVector() const;
int getRandSeed() const;
bool save(QString);
friend QDataStream& operator <<(QDataStream &dataStream, const CloudData &cd)
{
dataStream << cd.getPolyVector() << cd.getPathPointVector()
<< cd.getSupPointVector() << cd.getRandSeed();
return dataStream;
}
private:
QVector<QPoint> m_polyVector;
QVector<QPoint> m_pathPointVector;
QVector<QPoint> m_supPointVector;
int m_randSeed;
};
CloudData.cpp
#include "clouddata.h"
#include <QFile>
CloudData::CloudData()
{
}
void CloudData::setPolyVector(QVector<QPoint> pVec)
{
m_polyVector = pVec;
}
void CloudData::setPathPointVector(QVector<QPoint> ppVec)
{
m_pathPointVector = ppVec;
}
void CloudData::setSuppPointVector(QVector<QPoint> spVec)
{
m_supPointVector = spVec;
}
void CloudData::setRandSeed(int randSeed)
{
m_randSeed = randSeed;
}
bool CloudData::save(QString filename)
{
QFile file(filename);
if(!file.open(QIODevice::WriteOnly))
return false;
QDataStream out(&file);
out.setVersion(QDataStream::Qt_4_8);
out << this;
file.close();
return true;
}
And in the end, here is the function, which calls save():
void CloudWidget::saveCloudData()
{
QString filename = QFileDialog::getSaveFileName(this,tr("Save cloud clutter data"),
"/Users/Admin/Downloads/", "Cloud Clutter Data (*.ccd)");
m_cloudData.setPolyVector(m_polygon);
m_cloudData.setPathPointVector(m_pathPointVector);
m_cloudData.setSuppPointVector(m_supPointVector);
m_cloudData.save(filename);
}
I believe the line:
out << this;
in the save() method should be:
out << *this;
The << operator works on a reference to the class, not a pointer to the class.
The following test code illustrates this:
#include <QFile>
#include <QTextStream>
#include <QDebug>
class StreamTest
{
public:
StreamTest() { var1 = "var1"; var2 = "var2"; }
QString var1;
QString var2;
friend QTextStream& operator <<(QTextStream &textStream, const StreamTest &st)
{
textStream << st.var1 << st.var2;
return textStream;
}
void save(void)
{
QString str_1;
QTextStream text_stream_1(&str_1);
text_stream_1 << this;
qDebug() << str_1;
QString str_2;
QTextStream text_stream_2(&str_2);
text_stream_2 << *this;
qDebug() << str_2;
}
};
int main(int argc, char *argv[])
{
StreamTest st;
st.save();
}
Running the code generates the output:
"0x7fff18070c10"
"var1var2"
this prints the pointer value while *this prints the desired output.