0

the title might be a bit misleading, but I want to give some instance of a class an instance of a different class through polymorphism. I think that may have been even more misleading so I'll give an example;

Say I have a class called Spell, that is a parent class to the class Firebolt. I want another class, say Character, to be able to have the spell, 'Firebolt', in an its memory without ever having to #include the files for 'Firebolt'.

Now, I can think of a way that prior games have done this before. By giving each spell (or whatever else specific class type) a static const string ID or name and in spell having some function that can access this ID/name and return a new Firebolt() if they are the same.

This sounds pretty good actually, the problem I'm having is I don't know how to code this. I'm not sure how I can access these ID's from the parent class, and I'm not sure how to make a virtual function that will actually return the correct Spell. Any help would be amazing. I'll also provide the actual class code I'm working with here in case it might help you guys to answer, or someone with a similar problem to solve it.

The parent class;

class Art {
    std::string name;
    int EPCost;
    int castTime;
    int AoESize;

public:
    Art(std::string n, int cp, int ct, int as):name(n), EPCost(cp), castTime(ct), AoESize(as) {}

    virtual ~Art() {}

    static Art* findArt(std::string ID);

    int getAoESize() {return AoESize;}

    std::string getName() {return name;}
    int getEPCost() {return EPCost;}

    virtual int getBaseDamage() = 0;
};

The subclass;

class FireBolt:public Art {
    static const std::string name;
    static const int EPCost;
    static const int castTime;
    static const int AoESize;
    static const std::string ID;

public:
    FireBolt():Art(name, EPCost, castTime, AoESize) {}

    ~FireBolt() {}

    int getBaseDamage();
};
Cool Dudde
  • 33
  • 6
  • Any reason you don't want to use polymorphism for this? – john Feb 16 '19 at 10:12
  • Perhaps not thinking about returning the correct `Spell` would help. What about just making it perform an `action()` (via polymorphism) and not worry about which subclass it is that performs it? – Ted Lyngmo Feb 16 '19 at 10:13
  • @john I dont think I ever said that I didnt want to use polymorphism? Im not 100% sure I know what you mean Ted – Cool Dudde Feb 16 '19 at 10:16
  • 1
    `FireBolt` implements something common to all `Spell`s - I chose to call that `action()`. Whenever the owner of said `Spell` wants to use it, just call its `action()`. – Ted Lyngmo Feb 16 '19 at 10:19
  • I think we're both a bit confused. It seems your actual question is how to create a class from an ID, that's strictly independent of the issue of polymorphism (although a polymorphic hierarchy is one place you might want to do that). – john Feb 16 '19 at 10:21
  • @john Sorry if the title is wrong or the wording misleading. What would be a better way to word this so that someone else with the same problem can find this? – Cool Dudde Feb 16 '19 at 10:26
  • I don't know, how to create a class from an identifier, sounds OK to me. BTW I'm positive this question has been asked before on SO, so you might do a little searching. – john Feb 16 '19 at 10:30
  • @CoolDudde For instance https://stackoverflow.com/questions/1096700/instantiate-class-from-name – john Feb 16 '19 at 10:33
  • @CoolDudde The straight way is to use a [_Decorator Pattern _](https://sourcemaking.com/design_patterns/decorator) for your `Character`class. Though that won't work well with collecting specific enhancements over time for a specific `Character` instance, – πάντα ῥεῖ Feb 16 '19 at 10:39

1 Answers1

1

All you need to do is make your FireBolt::ID public.

class FireBolt:public Art {
public:
    static const std::string ID;
    ...
};

Art* Art::findArt(const std::string& ID)
{
    if (ID == FireBolt::ID)
        return new FireBolt(...);
    ...
}
john
  • 85,011
  • 4
  • 57
  • 81
  • I dont think this will work because Art does not have access to FireBolt's ID like that. Firebolt is a subclass of Art, so Art does not inherit Firebolts ID variable. – Cool Dudde Feb 16 '19 at 10:18
  • 1
    @CoolDudde It will work because `FireBolt::ID` is both public and static. Try it. – john Feb 16 '19 at 10:22
  • OK, so the issue for you is not wanting to `#include "FireBolt.h"`. In that case just make the IDs global constants and put their declarations in the header file along with `Art`. – john Feb 16 '19 at 10:26