Jump to content
  • Advertisement
Sign in to follow this  
Muncher

i thought i understood virtual functions, but

This topic is 4860 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

Hello, I'm having trouble figuring out how virtual functions are working; plz help :) I have 2 classes (Base and Derived) with one virtual function called "printString". Derived overwrites Base's printString (as it should) - but if i store Derived in a vector, and call printString - it calls Base's printString!!?? Here is the source, it should work fine if you paste it into a new workspace Am i doing something wrong?


#include <vector>
#include <iostream>

using namespace std;

// Base class
class Base
{
public:
	Base(){};
	~Base(){};

	virtual void printString(void){ cout << "in parent \n"; };
};

// Derived class
class Derived : public Base
{
public:
	Derived(){};
	~Derived(){};

	virtual void printString(void){cout << "in child \n"; };
};

// Main
void main (void)
{
	Base *d = new Derived();

	d->printString();         // Prints in child

	// put in a vector
	vector <Base> v;
	v.push_back(*d);
	v[0].printString();       // Prints out parent, whats happening? :\
}

Any comments would be great Muncher

Share this post


Link to post
Share on other sites
Advertisement
Virtual functions only work with pointers. You would need to have a Vector<Base *> rather than a Vector<Base>

Share this post


Link to post
Share on other sites
Quote:
Original post by Muncher
Hello,

I'm having trouble figuring out how virtual functions are working; plz help :)

I have 2 classes (Base and Derived) with one virtual function called "printString".
Derived overwrites Base's printString (as it should) - but if i store Derived in a vector, and call printString - it calls Base's printString!!??


Here is the source, it should work fine if you paste it into a new workspace
Am i doing something wrong?

*** Source Snippet Removed ***

Any comments would be great
Muncher


Try making your vector of type <Base*> - when you create a vector of type <classname>, it'll create a copy of that class - hence, it'll create a Base version of it here... if you store the pointer to the class (base or derived), the vtable pointers should remain intact and the runtime should be able to determine which classtype to call from.

(at least I think that's right! =)

Share this post


Link to post
Share on other sites
That's because it's a vector specifically of type Base
If you wish to use abstract storage you'll need a vector of pointers to type base instead:


std::vector<Base*> vector;
vector.push_back(new Derived());
vector[0]->printString();
delete vector[0];
vector.pop();


Also another way to look @ why it can't work with a fixed type like that is that you're only allocating enough space for type Base - later derived types might be larger
Thus a go-between pointer is used to access the variable of abstract size (guarenteed to have a minimum of Base)

edit: LOL I'm sloooooww

Share this post


Link to post
Share on other sites
Quote:
Original post by Jingo
Don't forget the virtual destructor.


To expand on this:

The base class must have a virtual destructor so that the derived class has it's destructor correctly called. Failure to do so will cause only ~Base() to be called if delete is called on a pointer of type (Base *). Generally, if there's a chance the object will be destroyed through a base pointer, the destructor should be made virtual. It will not induce any extra overhead if other members of the class are virtual, so it's considered good practice by many to make any class with virtual members have a virtual destructor, just to be on the safe side. There's even talk of making this automatic in a future revision of the C++ standard...

Also, I might recommend using The Boost Librarys, specifically their shared_ptr smart pointer. It allows one to store pointers and thus polymorphic behavior just like normal raw pointers, but will automatically delete the object as well when all the pointers are destroyed so that one does not end up with memory leaks:

#include <boost/shared_ptr.hpp>
#include <vector>

void this_leaks( void ) {
std::vector< foo * > foos;
foos.push_back( new foo );
foos[0]->function();
//leak: when foos goes out of scope, the pointers will be destroyed but the object pointed to not.
}

void this_dosnt_leak( void ) {
std::vector< boost::shared_ptr< foo > > foos;
boost::shared_ptr< foo > my_foo( new foo );
foos.push_back( my_foo );
foos[0]->function();
//no leak: when both shared_ptrs go out of scope (my_foo and the one inside of foos) the object will be automatically destroyed.
}


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!