Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
编译器如何解析访问非虚拟数据成员C++; 当我怀疑这个问题时,我正在阅读C++对象。假设有两个类 class X { virtual int def() { }; } class Y { virtual int abc() { }; } class Z : public X,public Y { virutal int abc() { return a }; int a; }_C++_Inheritance - Fatal编程技术网

编译器如何解析访问非虚拟数据成员C++; 当我怀疑这个问题时,我正在阅读C++对象。假设有两个类 class X { virtual int def() { }; } class Y { virtual int abc() { }; } class Z : public X,public Y { virutal int abc() { return a }; int a; }

编译器如何解析访问非虚拟数据成员C++; 当我怀疑这个问题时,我正在阅读C++对象。假设有两个类 class X { virtual int def() { }; } class Y { virtual int abc() { }; } class Z : public X,public Y { virutal int abc() { return a }; int a; },c++,inheritance,C++,Inheritance,现在我了解的是Y和Z在它们的虚拟表中都有对Z::abc()的引用,这有助于解析要调用的正确函数。考虑 Y *y = new Z; Z *z = new Z; y->abc() // I understand this is done by reaching the vptr of y by this = this + sizeof (X) and z->abc() // z has its own vptr reachable 我的理解是,在这两种情况下,都会传递“this”指针,

现在我了解的是Y和Z在它们的虚拟表中都有对Z::abc()的引用,这有助于解析要调用的正确函数。考虑

Y *y = new Z;
Z *z = new Z;
y->abc() // I understand this is done by reaching the vptr of y by this = this + sizeof (X)
and z->abc() // z has its own vptr reachable
我的理解是,在这两种情况下,都会传递“this”指针,在找到要调用的正确abc()之后,程序如何达到int值“a”

编译器如何根据传递的对象类型正确计算“int a”的地址?

您可以

 virtual int abc() { return a };
作为

因此,对于每个非静态成员函数,都有一个
隐藏的
指针指向对象。因此,只要编译器能够找到虚拟方法,它就知道
a
在哪里。

您可以处理

 virtual int abc() { return a };
作为


因此,对于每个非静态成员函数,都有一个
隐藏的
指针指向对象。因此,只要编译器能够找到虚拟方法,它就知道
a
在哪里。

以John的观点为基础,如果派生类重写基类方法,编译器将自动为派生类中的vtable创建所谓的vpointer。
这个
指针在派生类的幕后指向vpointer,然后指向派生类的vtable。这就是多态性的工作原理

以John的观点为基础,如果派生类重写基类方法,编译器将自动为派生类中的vtable创建称为vpointer的对象。
这个
指针在派生类的幕后指向vpointer,然后指向派生类的vtable。这就是多态性的工作原理

这些都是实现细节,不同的编译器做不同的事情。解决此问题有两种常见方法,但都取决于修复此
指针在函数定义中所指的内容

一种方法是让
这个
指针始终指向完整的对象(至少在虚拟函数的最终重写器级别)。在这种方法中,在存在多重继承的情况下,vtable中的条目不包含指向实际函数的指针,而是指向一个蹦床的指针,该蹦床调整
这个
指针,然后跳转到重写器。这种方法的优点是,对于最左边的非空基,以及在所有单一继承的情况下,vtable中的条目实际上是重写器,并且没有相关的开销。这是ItAudioC++中的方法,它在不同的操作系统中使用,包括Linux。
另一种方法是始终传递首先声明成员函数的子对象的地址。在这种情况下,调用者在跳过vtable之前调整
this
指针以引用子对象。与第一种情况一样,如果没有偏移量(第一个非空基,单继承),编译器不需要添加任何调整,也不会产生任何成本。在最终重写器的实现中,编译器使用声明函数的基指针的偏移量,而不是完整对象的偏移量。我相信在Windows /VisualStudio中是这样的,但是不要在这里说我的话,因为我没有访问VS C++ ABI来确认这个。
第三种方法是将调整直接存储在vtable中。这种方法不太常见,即使不需要更新(通过添加0),也会产生调整抵销的成本。我不知道目前有哪种编译器使用这种方法。

这些都是实现细节,不同的编译器做不同的事情。解决此问题有两种常见方法,但都取决于修复此
指针在函数定义中所指的内容

一种方法是让
这个
指针始终指向完整的对象(至少在虚拟函数的最终重写器级别)。在这种方法中,在存在多重继承的情况下,vtable中的条目不包含指向实际函数的指针,而是指向一个蹦床的指针,该蹦床调整
这个
指针,然后跳转到重写器。这种方法的优点是,对于最左边的非空基,以及在所有单一继承的情况下,vtable中的条目实际上是重写器,并且没有相关的开销。这是ItAudioC++中的方法,它在不同的操作系统中使用,包括Linux。
另一种方法是始终传递首先声明成员函数的子对象的地址。在这种情况下,调用者在跳过vtable之前调整
this
指针以引用子对象。与第一种情况一样,如果没有偏移量(第一个非空基,单继承),编译器不需要添加任何调整,也不会产生任何成本。在最终重写器的实现中,编译器使用声明函数的基指针的偏移量,而不是完整对象的偏移量。我相信在Windows /VisualStudio中是这样的,但是不要在这里说我的话,因为我没有访问VS C++ ABI来确认这个。
第三种方法是将调整直接存储在vtable中。这种方法不太常见,即使不需要更新(通过添加0),也会产生调整抵销的成本。我不知道目前有哪个编译器使用这种方法。

X
abc()
一无所知。这是一个输入错误bad@HansPassant我知道“a”在偏移量8处。但是,根据调用对象的类型,这个指针将位于不同的位置。我的疑问是,函数abc()如何到达起始内存位置,以获取“a”的地址作为这个+偏移量?因为这个指针