0

I have a function which takes in a vector of Cp pointers, and dynamic_cast them into pointer of derived pointers. When I try to get a member variable of the derived class, it crashes:

void DrawSystem::update(vector<Cp*> currentArgs)
{
    cout << currentArgs[0]->type;
    //Doesn't crash here
    GraphicsCp* graphics = dynamic_cast<GraphicsCp*>(currentArgs[0]);
    cout << graphics->type; //Crashes here
    sf::Vector2f pos = dynamic_cast<PosCp*>(currentArgs[1])->pos;
    cout << pos.x << " || " << pos.y << endl;
}

Does anyone know why this is?

Edit: Here is all the relevant code:

void GameObject::updateSystems() {
    for(vector<System*>::const_iterator i = Systems.begin(); 
        i != Systems.end(); 
        ++i) {
        vector<Cp*> args;
        for(vector<cptype>::const_iterator j = (*i)->args.begin(); 
            j != (*i)->args.end(); 
            ++j) {
            args.push_back(Cps[*j]);
        }
        (*i)->update(args);
    }
}

class GameObject {
    public:
        GameObject();
        virtual ~GameObject();

        void addCp(const cptype&, Cp);
        void addSystem(const systype&);

        map <cptype, Cp*> Cps;
        vector <System*> Systems;

        void updateSystems();
        virtual void update() {}
        virtual void draw() {}
        virtual bool isVisible() { return false; }
};

class GraphicsCp : public Cp {
    public:
        GraphicsCp(); //TEMP
        GraphicsCp(sf::Texture*, sf::Vector2f);
        virtual ~GraphicsCp();

        sf::Sprite sprite;
        sf::Vector2f frameDim;
        sf::Vector2i currentTextureRectPos;

        void update(Player& player, sf::RenderWindow&); //TEMP
    private:
        sf::RectangleShape rectangle; //TEMP
};

class Cp {
    public:
        Cp();
        virtual ~Cp();

        virtual void update() {} //TEMP

        cptype type;
};

Player::Player() {
    addCp("Pos", PosCp());

    sf::Texture* texture = &Game::level.levelImageManager.playerSprite;
    sf::Vector2f frameDim(54, 93);
    addCp("Graphics", GraphicsCp(texture, frameDim));

    addSystem("Draw");
}

void GameObject::addCp(const cptype& type, Cp cp) {
    Game::level.levelCpManager.CpVecs[type].push_back(cp);
    Cps[type] = &Game::level.levelCpManager.CpVecs[type].back();
}

void GameObject::addSystem(const systype& type) {
    Systems.push_back(Game::level.levelSystemManager.systems[type].get());
}
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
Yaxlat
  • 665
  • 1
  • 10
  • 25
  • 4
    You should check the result of `dynamic_cast(currentArgs[0]);` before using it. – πάντα ῥεῖ Oct 05 '14 at 14:32
  • `dynamic_cast(currentArgs[0]);` will return a `nullptr` if either `currentArgs[0]` contains a `nullptr`, or contains a pointer to an object, that wasn't derived from `GraphicsCp`. The _crash_ indicates, that you've got a `nullptr` as result, and you're dereference it in the next line of code. – πάντα ῥεῖ Oct 05 '14 at 15:07
  • Hey I know this is a badly worded question and all, but I still can't figure out what the problem is. I checked and it isn't a nullptr (you can see in the edited question, line 3 works) – Yaxlat Oct 05 '14 at 16:32
  • Well, you didn't check if `dynamic_cast(currentArgs[0]);` failed though: `if(graphics) { // ...` – πάντα ῥεῖ Oct 05 '14 at 16:37
  • It did fail, sorry I thought I put that :). But that's weird because it clearly isn't a null pointer until it is dynamic_cast. What does that mean, and how can I fix it? Thank you for your patience. – Yaxlat Oct 05 '14 at 16:45
  • _"What does that mean, and how can I fix it?"_ As mentioned, ensure that `currentArgs[0]` contains some pointer to `GraphicsCp*` or something derived from `GraphicsCp`, when you call this function. – πάντα ῥεῖ Oct 05 '14 at 16:47
  • It does, that is what the line: cout << currentArgs[0]->type; checked – Yaxlat Oct 05 '14 at 16:51
  • Absolutely, a 100% sure? Edit your question to show the relevant calling code, and the relations of `class Cp` and `class GraphicsCp` please. I don't believe you found a compiler implementation bug with `dynamic_cast<>` for your case. – πάντα ῥεῖ Oct 05 '14 at 16:54
  • I agree with you. One sec – Yaxlat Oct 05 '14 at 16:56
  • I added all the relevant code. It is quite a lot, sorry about that. – Yaxlat Oct 05 '14 at 17:01
  • Seems like you're a victim of [slicing](http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c) at some point in your code, and your `GraphicsCp` is degenerated to a sliced copy of `Cp`, thus no `GraphicsCp*` is actually stored in your `std::vector`. – πάντα ῥεῖ Oct 05 '14 at 17:09
  • Ah I see. Thanks. How do I avoid said splicing? – Yaxlat Oct 05 '14 at 17:34
  • _"How do I avoid said splicing?"_ Well that's a broad topic. IMHO you should go for using [_'smart pointers'_](http://en.cppreference.com/w/cpp/memory) instead of managing raw pointers all along. Use `unique_ptr<>` to delegate ownership at clients, use `weak_ptr` to check validity, use `shared_ptr`, if you don't want to care of ownership in particular – πάντα ῥεῖ Oct 05 '14 at 19:12
  • _"thanks so much for your help :)"_ De Nada! If you find a consolidate way how to solve your problem, or find words, why your actual approach didn't work, please don't hesitate to post your own answer with detailed explanations here. It wiöö be appreciated by future researchers on the topic. – πάντα ῥεῖ Oct 05 '14 at 20:01

0 Answers0