Search code examples
c++inheritancepolymorphismvirtual-functionsobject-slicing

Why do virtual functions need to be passed with a pointer and not by value(of the object)?


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

Solution

  • 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:

    • pointer of base type, or
    • reference of base type

    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.