我想我理解虚方法和vtable的概念,但我不明白为什么将对象作为指针(或引用)传递和通过值传递(哪种类型的vtable或其他东西)有区别?
为什么像这样的东西会起作用:
Material* m = new Texture;
poly->setMaterial(m);
// methods from Texture are called if I keep carrying the pointer around
而不是这个?:
Material m = Texture();
poly->setMaterial(m);
// methods from Material are called if I pass the value around
发布于 2011-04-28 15:31:35
因为如果通过值传递,则会发生object slicing,并且无法实现运行时多态性。在您的代码中,正是这一行的Material m = Texture()
导致了对象切片。因此,即使通过指针(或引用)传递m
,也无法实现运行时多态性。
此外,运行时多态性是通过以下方式实现的:
基类型的
的
因此,如果您想要运行时多态性,可以使用基类型指针或引用,下面是几个如何实现运行时多态性的示例:
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 '&'
只有在最后一行中,您没有实现运行时多态性。
发布于 2011-04-28 15:31:31
Material m = Texture()
将调用构造函数Material::Material(Texture const &)
,或者,如果该构造函数不可用,则调用Material
复制构造函数,该构造函数构造Material
而不是Texture
。
这不可能为您构建一个Texture
对象,因此该对象被分割为基类对象。
发布于 2011-04-28 15:33:30
虚函数在您的两个示例中都能很好地工作。它们完全按照它们应该工作的方式工作。
虚拟函数的整个思想是,根据调用中使用的对象的动态类型来调度对这种函数的调用。(不幸的是,您在示例中没有展示如何进行这些调用。)
在第一个示例中,您创建了一个Texture
类型的对象。对象的动态类型是Texture
,因此虚拟调用转到Texture
的方法。
在第二种情况下,您创建了一个Material
类型的对象。对象的动态类型是Material
,因此虚拟调用转到Material
的方法。
非那样做不行。一切都如人们所期望的那样工作。如果您的期望与此不同,那么您应该让它们更好地与语言保持一致。
https://stackoverflow.com/questions/5821075
复制