Why should virtual functions be passed with a pointer, and not by value (of an object)?

I think I understand the concept of virtual methods and vtables, but I don’t understand why there is a difference between passing an object as a pointer (or link) and passing it by value (what kind of vtable trim or something?)

Why is 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 that ?:

 Material m = Texture(); poly->setMaterial(m); // methods from Material are called if I pass the value around 
+6
source share
7 answers

Because if you pass by value, the objects will be split , and the run-time polymorphism cannot be achieved. And in your code, the very line Material m = Texture() causes the splitting of objects. Therefore, even if you pass m pointer (or reference), runtime polymorphism cannot be achieved.

In addition, run-time polymorphism is achieved by:

  • base type pointer or
  • base type link

So, if you need polymorphism at runtime, you use either a pointer or a link of the base type, and here are some examples of how you can achieve polymorphism at runtime:

 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 do you not achieve polymorphism at run time.

+14
source

Material m = Texture() will call the constructor Material::Material(Texture const &) or, if it is not available, the copy constructor Material , which will build Material , not a Texture .

It is not possible to build a Texture object for you, so the object is sliced ​​into an object of the base class.

+4
source

Virtual functions work great in both of your examples. They work exactly the way they should work.

The whole idea of ​​a virtual function is that a call to such a function is sent in accordance with the dynamic type of the object used in the call. (Unfortunately, you did not show in your examples how you make these calls.)

In the first example, you created an object of type Texture . The dynamic type of the Texture object, so virtual calls go to Texture methods.

In the second case, you create an object of type Material . The dynamic type of the Material object, so virtual calls go to the Material methods.

That's all. Everything works as expected. If your expectations differ from this, then you should simply bring them into line with the language.

+3
source

Because Material m = Texture(); cuts off an object - at this moment you have only Material .

+2
source

When you assign a Texture object to a material, it is cut into material. Therefore, any call to m will only send material functions.

Material m takes place for one Material object.

Using simple structures, I illustrate what is meant by cutting:

 struct A { int a; }; struct B : public A { int b; }; A objectA = B(); objectA.b = 1; // compile error, objectA does only have the properties of struct A 
+1
source
 Material m = Texture(); 

Create a temporary Texture , then create a Material by copying the Material part of the Texture . This is called slicing, and usually this is not what you want.

+1
source
 class Base { //Members }; class Derived1:public Base { //Members }; int main() { Base obj1; Derived1 obj2; obj1 = obj2; //Allowed Since Public Inheritance } 

When obj1 = obj2 only those members of the Deried Class obj2 that are inherited from the base class are copied to obj1, the remaining members of the Derived Class are truncated. This is simply because the base class obj1 does not know the members of the Derived class. This phenomenon is called Object Slicing .

In your case, when you call Material m = Texture() , it only contains the members of Material , and therefore, any function call on the object calls the member functions from Material & not Texture .

+1
source

Source: https://habr.com/ru/post/886894/


All Articles