Reputation: 4431
I'm new to C++ and I'm trying to figure out this problem I'm having with my constructor for one of my classes. What happens is... all my variables are initialized properly except two (health and type).
#pragma once
#include <irrlicht.h>
#include <vector>
#include <cassert>
using namespace irr;
using namespace core;
using namespace scene;
enum
{
PLAYER = 0,
NPC = 1,
SOLDIER = 2,
CHAINGUNNER = 3
};
class Model
{
public:
Model(void);
Model(int id, std::vector<ISceneNode*> modelVec, int modType);
~Model(void);
std::vector<int> path;
std::vector<ISceneNode*> model;
int endNode;
int type;
int animate;
int health;
u32 lastAnimation;
private:
int mId;
};
#include "Model.h"
Model::Model(void)
{
//assert(false);
}
Model::Model(int id, std::vector<ISceneNode*> modelVec, int modType)
{
path = std::vector<int>();
model = modelVec;
endNode = 0;
type = modType;
animate = 0;
health = 100;
lastAnimation = 0;
mId = id;
}
Model::~Model(void)
{}
I create a model with Model soldier(id, model, SOLDIER) Everything is set properly except type and health. I've tried many different things, but I cannot figure out my problem. I'm not sure but the default constructor is being called. It doesn't make sense because I make no called to that constructor.
Thanks,
vector<ISceneNode*> model;
model.push_back(soldierBody);
model.push_back(soldierHead);
model.push_back(soldierWeapon);
cout << "Id of char: " << id << endl;
Model soldier(id, model, SOLDIER);
modelMap[id] = soldier;
Upvotes: 2
Views: 4537
Reputation: 700
You do:
Model soldier(id, model, SOLDIER); //1
modelMap[id] = soldier; //2
What happens here?
1. New object is created, using consructor you have provided.
2. The so-called copy-constructor copy assignment operator is called to copy soldier
to modelMap[id]
. You haven't defined your own copy-constructor copy assignment operator so one default is created for you by compiler, it is in most cases just copying byte-by-byte whole data-structure to the new memory address. However you have vector of pointers in your class, so compiler should call copy-constructor of vector... And I don't know (maybe someone with greater experience would know exactly what happens now) what is the result copy-constructor, I don't know if standard clearly defines 'default copy-constructor'.
So it is possible, that the whole structure is copied to the modelMap[]
but with some random data.
If you create a copy-constructor (its declaration in your case will look something like If you override copy assignment operator (best, if you make both things), you have control over everything that is done while copying your object to another variable/object.Model::Model(const Model& myModel);
, copy-constructor always takes reference to object of its type as an argument)
Download eg. Bruce Eckel's Thinking in C++, V. 1 [1], or search somewhere on the Net how to do it (probably this will be good, didn't read whole article, http://www.learncpp.com/cpp-tutorial/911-the-copy-constructor-and-overloading-the-assignment-operator/).
[1] Downloadable on his website, mindview.net, as a new user I can paste only one link, so cannot link it here myself :P.
Upvotes: 1
Reputation: 264331
This lines:
modelMap[id] = soldier;
First default constructs the Model inside the map.
The returned reference is then used with the assignment operator to copy the value of soldier into the value contained inside the map.
To test if it is working try:
Model soldier(id, model, SOLDIER);
std::cout << "TYPE(" << soldier.type << ") HEALTH(" << soldier.health << ")" std::endl;
modelMap[id] = soldier;
std::cout << "TYPE(" << modelMap[id].type << " HEALTH(" << modelMap[id].health << ")" std::endl;
If your class is not designed to be default constructible.
Then do not have a default constructor (this will just lead to problems).
Declare a default constructor in the private part of the class (no need for a body).
Without a default constructor you will not be able to use the operator[] on map. But you can get around this by using insert:
modelMap.insert(std::map<XX, Model>::value_type(id, soldier));
Upvotes: 2
Reputation: 354969
From the comments, you say that you are inserting these into a map like so:
modelMap[id] = Model(id, model, SOLDIER);
std::map::operator[]
requires that the mapped type be default constructible. When you call operator[]
on a map, if there is no mapped value with the given key, the map default constructs a new object, maps it to the given key, and returns a reference to that object.
You can get around this by using std::map::insert()
:
modelMap.insert(std::make_pair(id, Model(id, model, SOLDIER));
Upvotes: 2