0

I have a problem with C++ vector understanding: an object I get from vector is always a base abstract class and not a derived class that was added to it.

  1. I have a vector:

    vector<SceneNode*> children;
    

Where SceneNode is an abstract class with pure virtual functions.

  1. I add an instance of ImageSceneNode (that is derived from SceneNode) to this vector:

    lib::ImageSceneNode node(static_cast<TextureAsset*>(test));
    
    sceneManager.getRoot()->addChild(&node);
    

Where addChild function is:

   void SceneNode::addChild(SceneNode* child) noexcept {
        this->children.push_back(child);
    }
  1. Later when I iterate the vector the object inside is an instance of SceneNode and fails with a "pure virtual function" call error:

enter image description here

Can you please help, thank you!

serg.nechaev
  • 1,323
  • 19
  • 26
  • you cannot instantiate an abstract class, so you cannot have object of abstract class in your vector! – W.F. Mar 21 '15 at 10:13
  • He hasn't any objects of an abstract class in his vector, he has pointers to them, which is perfectly valid. – jensa Mar 21 '15 at 10:18
  • I know, but he said he had the instances of the pure abstract class, thus my comment... – W.F. Mar 21 '15 at 10:26
  • `if (false == children.empty)`, that looks like a coding guideline from the distant past, when compilers would not warn about stuff like `if (x = 1)`. In this case, it's even worse, because you already have a `bool` there, i.e. you can just write `if (!children.empty)`. – Christian Hackl Mar 21 '15 at 10:52

1 Answers1

4

The "pure virtual function call" error is most commonly encountered with an object that has been destroyed. I note that you're grabbing and holding a pointer to node, a variable with local scope. If you're trying to access that object from its pointer in children after the function has exited, you're going to run into errors like this one.

Sneftel
  • 40,271
  • 12
  • 71
  • 104
  • 1
    yep in my opinion as the Sneftel said you should do in your step 2 `sceneManager.getRoot()->addChild(new lib::ImageSceneNode(static_cast(test));` – W.F. Mar 21 '15 at 10:18
  • 2
    No, don't do that. `new` is a terrible thing that nobody should ever use. – Puppy Mar 21 '15 at 10:19
  • 2
    @Puppy Even though I agree that the "raw" use of the new operator is discouraged in modern C++ I don't think we should make absolute statements like that. If you know what you are doing using new is (of course) OK. – jensa Mar 21 '15 at 10:23
  • Thanks a lot! I was changing the code to use pointers instead of pass by "copy" and introduced this bug which now makes perfect sense... – serg.nechaev Mar 21 '15 at 10:28
  • 1
    @Puppy your statement is not based on any rational premise... You just don't like good old fashioned instantiation, it would be OK if you would not suggest that using new operator is always wrong, as it is not! – W.F. Mar 21 '15 at 10:34
  • @Puppy: *"Never use owning raw pointers and delete, except in rare cases when implementing your own low-level data structure (and even then keep that well encapsulated inside a class boundary)."* http://herbsutter.com/elements-of-modern-c-style/ However, I agree 100% with your statement as far as `new[]` is concerned. For that one I don't see any use case (and I guess Herb Sutter doesn't see one, either). – Christian Hackl Mar 21 '15 at 11:01
  • @ChristianHackl I don't see here C++11 tag – W.F. Mar 21 '15 at 11:20
  • @WojciechFrohmberg: Which would make the statement even more true, wouldn't it? (Also, the current convention here on SO seems to be that you can assume C++11 unless specified otherwise.) Of course, an even more important guideline for C++, be it 03 or 11, would be: "Avoid dynamic allocation, unless you actually need it." – Christian Hackl Mar 21 '15 at 11:25
  • @ChristianHackl here this "convention" is specified? There are certain people at SO who state that strict adherence to some not literally spelled convention is preffered over helping people solving their problems... Are you one of them? – W.F. Mar 21 '15 at 11:34
  • @ChristianHackl: see that the Puppy didn't provide alternative solution. He just decided to argue with mine... – W.F. Mar 21 '15 at 11:43
  • @WojciechFrohmberg: Please tell me how *"C++ is a general-purpose programming language based on C. Use this tag for questions about code compiled with a C++ compiler."* somehow means only one particular version of the C++ standard. If you were around here longer, you would see that people often post C++11 code even without the C++11 tag. And in a comment, it's perfectly OK to mention different aspects of a topic. That's one of the differences between comments and answers. FWIW, the link above actually *supports* your original statement, at least the way I understood you. – Christian Hackl Mar 21 '15 at 11:43