Reputation: 4305
These lines of code are run:
Enemy* enemy = new Enemy(m_pSceneManager,"enemy"+ss.str());
std::cout << "Enemy name = " << std::string(enemy->name) << std::endl;
Add(enemy->name,enemy);
in EnemyManager.cpp. EnemyManager inherits from GameObjectManager:
void GameObjectManager::Add(sf::String name,VisibleGameObject* obj){
std::cout << "GameObjectManager obj name = " << std::string(obj->name) << std::endl;
gameObjects.insert(std::pair<sf::String,VisibleGameObject*>(name,obj));
}
Enemy inherits from VisibleGameObject, which both have a public sf::String 'name' variable but only Enemy initializes it at any point (in its constructor). The output in the console window is this:
Enemy name = enemy0
GameObjectManager obj name =
Why does the name
revert to nothing? I'm assuming it's something to do with the fact that the argument is a VisibleGameObject* and not an Enemy* - if it is, how can I work around this? If I've made a mistake somewhere else, please tell me if there are any details I am missing that are required.
Thanks
Upvotes: 1
Views: 448
Reputation: 2129
Since, as you say both have a public sf::String 'name' variable but only Enemy initializes it at any point (in its constructor). , there are two name
subojects: one is a member of Enemy
and another is a subobject of VisibleGameObject
. Inside function Add
you explicitly refer to the latter one, so that is what you get, and it is not initialised.
You probably want to make name
a virtual function returning string; this will make function Add
to employ runtime polymorphism and call name()
from derived class, i.e. from Enemy
.
Simpler (but not necessarily better) design would be to make name
protected or public member of VisibleGameObject
and let Enemy
set it; that also means you will most likely want to remove name
from Enemy
, otherwise name
inherited from VisibleGameObject
will be hidden.
Upvotes: 1
Reputation: 40643
If I understand your description correctly, your code looks like this:
struct VisibleGameObject {
sf::String name;
};
struct Enemy : VisibleGameObject {
Enemy(SceneManager*, sf::String newName) : VisibleGameObject(), name(newName)
sf::String name;
};
struct GameObjectManager {
void GameObjectManager::Add(sf::String name,VisibleGameObject* obj){
std::cout << "GameObjectManager obj name = " << std::string(obj->name) << std::endl;
gameObjects.insert(std::pair<sf::String,VisibleGameObject*>(name,obj));
}
private:
std::map<sf::String, VisibleGameObject*> gameObjects;
};
struct EnemyManager : GameObjectManager {
void foo() {
//This code probably leads to a memory leak, but you might have solved it in some
//way that you are not showing.
Enemy* enemy = new Enemy(m_pSceneManager,"enemy"+ss.str());
std::cout << "Enemy name = " << std::string(enemy->name) << std::endl;
Add(enemy->name,enemy);
}
};
What this means is - when the Enemy
object is constructed, the Enemy::name
variable is initialised to hold "enemy"+ss.str()
. However, the VisibleGameObject::name
variable (which is in the VisibleGameObject part of the Enemy
) is initialised to hold its default value (in which it holds no text).
In EnemyManager::foo
, the name variable that is referenced is the one in Enemy
. In GameObjectManager::Add
, the name
variable that is referenced is the one in the VisibleGameObject
base member of Enemy
. VisibleGameObject::name
still has its default value, and so nothing gets printed.
Upvotes: 2