Jump to content
  • Advertisement
Sign in to follow this  
mychii

Problem on referencing a vector of derived class

This topic is 853 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi guys,

 

I want to make a reference to a vector of a base class, but I'm having trouble on casting it.

 

So I have a map<type_index, vector<Base*>>, and this map contains specific vector of pointers, pointers to derived class of the mentioned base class Base.

 

Now, I want to make a reference of one of the vector inside that map, but directly as the derived class, say a vector pointer vector<A*>* (or weak_ptr<vector<A*>> maybe, I haven't used it yet) that refers to one of the vector. A is a derived class of Base.

 

The problem is, as far as I know, I can't cast a reference of vector<Base*> directly to vector<A*>*. So I got to turn vector<A*>* into vector<Base*>* and make a description that says that it's a vector of A, which is definitely silly and confusing for anyone else to read. It's like, "Oh, it's a pointer to pointers of Base", and suddenly in definition file, it only points to vector<A*>. People can kick me.

 

However, I don't know the other solution as well to solve this or a better one. Can anyone help me?

 

The example code looks like this more or less:

class SomeContainer
{
        std::map<std::type_index, std::vector<Base*>> _bases;
...
	template <typename Type> std::vector<Base*>* SomeContainer::GetBase()
	{
		return &_bases[typeid(Type)];
	}
}

...

class ThatNeedsOneOfTheVector
{
        std::vector<Base*>* aList; // What in seven hells is this?
}

void ReferencingItHere()
{
        aList = SomeContainer::GetBase<A>(); // Oh, okay As is a reference to a vector of A pointers .. :/
        
        // sample of using it...
        if (aList->size() > 0)
            A* a = (A*)aList->at(0); // omg...
}

Also note that this is an example. In the real code I cannot turn SomeContainer class into a template class if that's the solution, hence the map of vectors to cover it, which gives me no choice than to use vector<Base*>. But if you got a better solution for this, I'd be happy to hear.

 

Thanks!  ^_^

Edited by Alectora

Share this post


Link to post
Share on other sites
Advertisement

This appears to be a misuse of inheritance. (refer to https://en.wikipedia.org/wiki/Liskov_substitution_principle) Generally you should be avoiding this type of cast and use dynamic_cast when it's unavoidable (this may be one of those cases). Trying to cast the vector itself is really not a good plan.

 

Could you explain more about what you're using this for? There may be a better pattern for this.

Share this post


Link to post
Share on other sites

This appears to be a misuse of inheritance. (refer to https://en.wikipedia.org/wiki/Liskov_substitution_principle) Generally you should be avoiding this type of cast and use dynamic_cast when it's unavoidable (this may be one of those cases). Trying to cast the vector itself is really not a good plan.

 

Could you explain more about what you're using this for? There may be a better pattern for this.

 

I have a list of component. Each of the component can be anything; a health component, damage component, character info, and anything else. However, I want my systems to deal specifically one of the type at a time. Like for example, I want a health management system to simply iterate with the health component (like decreasing all health regardless of who the entity that owns it). So I simply get that specific vector, which is the reason why I use map where I can just get that specific vector by key. I'm sure I don't want to iterate the whole vector of components and check if it's a health component right? That's simply the idea. Now I need the system to make reference to it, and turns out to be a problem.

 

I'm sure there's a better pattern for this, but I just don't know how, yet. Please help~  :wacko:

 

 

Is there a particular reason you're using a map of vectors instead of a multi_map?

 

Oh I didn't know about this one. I'll check it out. Basically it's as what I've answered to Khatharr. I hope it can do what I want.

Edited by Alectora

Share this post


Link to post
Share on other sites

Seems like I finally got a workaround for it, apparently it's quite simple, even though I'm not sure if it's still okay.

class SomeContainer
{
        std::map<std::type_index, std::vector<Base*>> _bases;
...
        // Now I return a reference instead of a pointer.
	template <typename Type> std::vector<Type*>& SomeContainer::GetBase()
	{
		return (std::vector<Type*>&)_bases[typeid(Type)]; // Seems like I'm able to cast it here...
	}
}

...

class ThatNeedsOneOfTheVector
{
        std::vector<A*>* aList; // No longer saying that it is pointing to a vector of base pointers anymore, but A pointers.
}

void ReferencingItHere()
{
        aList = &SomeContainer::GetBase<A>(); // get the address to it instead.
        
        if (aList->size() > 0)
            A* a = aList->at(0);
}

Edited by Alectora

Share this post


Link to post
Share on other sites

- Getting a reference or pointer into a map which might just delete that element sounds like a bad idea

- Also keeping pointers to components means that every time a system moves through a components vector, you'll have to dereference every single component (also true if getting a single component from that vector)

- If you really need to use pointers and pass them around, use smart pointers, otherwise someone is going to delete a component and you'll have a lot of fun debugging that

 

Since you already have a vector for every type of component why not just have multiple vectors of type std::vector<ComponentX> and some template magic to have multiple of these within the same pool? After that a loop iterates over one of these vectors and calls some system with a reference to every component.

 

Theres also quite some ECS implementations available to look at or use.

Edited by BloodyEpi

Share this post


Link to post
Share on other sites

- Getting a reference or pointer into a map which might just delete that element sounds like a bad idea

- Also keeping pointers to components means that every time a system moves through a components vector, you'll have to dereference every single component (also true if getting a single component from that vector)

- If you really need to use pointers and pass them around, use smart pointers, otherwise someone is going to delete a component and you'll have a lot of fun debugging that

 

Since you already have a vector for every type of component why not just have multiple vectors of type std::vector<ComponentX> and some template magic to have multiple of these within the same pool? After that a loop iterates over one of these vectors and calls some system with a reference to every component.

 

Theres also quite some ECS implementations available to look at or use.

Thanks for the input bloodyEpi. Yeah I'll be using weak ptr to track these later, it's just that I don't always implement them right away when designing it to know what and where. I had one experience where I start off with available smart pointers, and the code becomes bloated and gets to the point where I use them improperly. To name one, returning a vector containing shared pointers of a base class into the derived one is one hell of a kind. But I'm sure I will get there when it's possible.

 

I'm not sure what you mean by multiple vectors of type std::vector<ComponentX>, but if you mean I got to hardcode them one by one, I don't think I'm going to do that. I let the template and map handle the things, cause later I might not know what components the other people would make and add already.

 

Regarding to a component being deleted cause of these, yes that's true I got to wrap these things right, lol. Gonna check on this again.

 

I'd love to see your recommendations for me to read on the ECS implementations, meanwhile I'll look for more.

Share this post


Link to post
Share on other sites

I have a list of component. Each of the component can be anything; a health component, damage component, character info, and anything else. However, I want my systems to deal specifically one of the type at a time. Like for example, I want a health management system to simply iterate with the health component (like decreasing all health regardless of who the entity that owns it). So I simply get that specific vector, which is the reason why I use map where I can just get that specific vector by key. I'm sure I don't want to iterate the whole vector of components and check if it's a health component right? That's simply the idea. Now I need the system to make reference to it, and turns out to be a problem.
 
I'm sure there's a better pattern for this, but I just don't know how, yet. Please help~  :wacko:


While you've got the right idea, updating certain types together, this isn't a great way to go about it - certainly a central pool might seem inviting but it causes problems like this.

A better solution would be to have the thing which does the updating hold references to the components, that way you use concrete types in all the right places.

So;
[source]

class HealthComponent : Component
{

// I DO HEALTH THINGS!
// LOOK AT ME HEALTHING ALL OVER THE PLACE!
}

class HealthModule
{
std::vector<HealthComponent> HealthComponents;


void Update()
{
std::for_each(std::begin(HealthComponents), std::end(HealthComponents), [](HealthComponent &c) { c->Update(); };
}

//todo: include other code to get a health component and whatever...
}
[/source]

So in your main loop you'd do something like;

[source]
void GameUpdateYo()
{
PhysicsModule::Update();
DamageModule::Update();
HealthModule::Update();
}

// or
std::vector<Module*> modules:

void GameUpdateYo()
{
std::for_each(begin(modules), end(modules), [](Module* m) { m->Update(); };
}
[/source]

The former is hard coded, the latter allows for expansion and even dynamic/startup reordering depending on how you want to register the modules in. Edited by phantom

Share this post


Link to post
Share on other sites

 

I have a list of component. Each of the component can be anything; a health component, damage component, character info, and anything else. However, I want my systems to deal specifically one of the type at a time. Like for example, I want a health management system to simply iterate with the health component (like decreasing all health regardless of who the entity that owns it). So I simply get that specific vector, which is the reason why I use map where I can just get that specific vector by key. I'm sure I don't want to iterate the whole vector of components and check if it's a health component right? That's simply the idea. Now I need the system to make reference to it, and turns out to be a problem.
 
I'm sure there's a better pattern for this, but I just don't know how, yet. Please help~  :wacko:


While you've got the right idea, updating certain types together, this isn't a great way to go about it - certainly a central pool might seem inviting but it causes problems like this.

A better solution would be to have the thing which does the updating hold references to the components, that way you use concrete types in all the right places.

So;
[source]

class HealthComponent : Component
{

// I DO HEALTH THINGS!
// LOOK AT ME HEALTHING ALL OVER THE PLACE!
}

class HealthModule
{
std::vector<HealthComponent> HealthComponents;


void Update()
{
std::for_each(std::begin(HealthComponents), std::end(HealthComponents), [](HealthComponent &c) { c->Update(); };
}

//todo: include other code to get a health component and whatever...
}
[/source]

So in your main loop you'd do something like;

[source]
void GameUpdateYo()
{
PhysicsModule::Update();
DamageModule::Update();
HealthModule::Update();
}

// or
std::vector<Module*> modules:

void GameUpdateYo()
{
std::for_each(begin(modules), end(modules), [](Module* m) { m->Update(); };
}
[/source]

The former is hard coded, the latter allows for expansion and even dynamic/startup reordering depending on how you want to register the modules in.

 

 

Ah yes that seems to be an interesting way to keep them concrete. How if I want to have these modules to interact to other ones? For example, say I have a matrix transformation module that contains all the xyz position etc information, and is used by the physics module? Do i just need to have the modules to reference to each other, by the topic, in a way to keep the component list stay concrete and hidden? Or do I have to do that on something other than module; system classes that specifically do those interactions?

Edited by Alectora

Share this post


Link to post
Share on other sites
The way I've seen it done previously is to have modules declare dependencies and then have a post-init step which passes pointers around so that modules can link to each other as required.

However, that's probably not a good solution - instead a better one is probably for the phyiscs component to take a reference to the 'transform' component of the object they are both a part of. Precisely how you'd do that however depends on how things are setup in your case, but it could look something like;

[source]
class PhysicsComponent : component
{
Transform * targetTransform;
void setTransform(Transform * t) { targetTransform = t; };
}

class PhysicsModule
{
void AddToGameObject(GameObject *go)
{
TransformComponent * t = go.getComponent<Transform>();
PhysicCompnent p;
p.setTransform(t);
go.addComponent(p);
}
}
[/source]

Plumbing depends on your setup and other details need to be resolved, but that's the basic idea :)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!