I think I understand the concept of virtual methods and vtables, but I don't understand why there is a difference between passing the object as a pointer(or reference) and passing it by value (which kind of scraps the vtable or something?)
Why would something like this work:
Material* m = new Texture;
poly->setMaterial(m);
// methods from Texture are called if I keep carrying the pointer around
And not this?:
Material m = Texture();
poly->setMaterial(m);
// methods from Material are called if I pass the value around
Because if you pass by value, then object slicing will occur, and runtime polymorphism cannot be achieved. And in your code, the very line Material m = Texture()
causes object slicing. So even if you pass m
by pointer (or reference), runtime polymorphism cannot be achieved.
Also, runtime polymorphism is achieved through:
So if you want runtime polymorphism, you've use either pointer or reference of base type, and here are few examples how you can achieve runtime polymorphism:
Material* m1 = new Texture();
poly->setMaterial(m1); //achieved
Texture* t1= new Texture();
poly->setMaterial(t1); //achieved
Texture t2;
poly->setMaterial( &t2); //achieved : notice '&'
Material & m2 = t2;
poly->setMaterial( &m2 ); //achieved : notice '&'
Material m3;
poly->setMaterial( &m3 ); //NOT achieved : notice '&'
Only in the last line you don't achieve runtime polymorphism.