在Bjarne Stroustrup的C ++编程语言中,据说可以在不同的地址空间之间传递指向虚拟成员函数的指针。
因为指向虚拟成员的指针是一种偏移量,所以它不依赖于 对象在内存中的位置。因此,指向虚拟成员的指针可以是 只要使用相同的对象布局,就在不同的地址空间之间传递 同时。像指向普通函数的指针一样,指向非虚函数 不能在地址空间之间交换。
但是,我不明白为什么指向非虚函数的指针不能。就像指向虚函数的指针一样,它也像Bjarne Stroustrup指出的那样充当索引。
但是,指向成员的指针不是指向一块内存的指针 指向变量的指针或指向函数的指针是。它更像是一个偏移量 进入数组的结构或索引,但当然是一个实现 考虑到数据成员,虚拟功能之间的差异, 非虚函数等。
当然,我理解虚函数和非虚函数(如vtbl等)之间的区别。但是,在每个类的实例化中,它不像在内存上再次分配相同的成员函数,这意味着我们无法根据对象的内存地址计算成员函数的内存位置。换句话说,非虚函数不依赖于对象在内存中的位置。我认为只有一个接口(=函数)和许多对象(=可能表示)。如果指向非虚函数的指针只是成员函数之间的标识符,则无法在进程之间传递和使用它是没有意义的。
答案 0 :(得分:2)
与虚函数指针一样,它也像Bjarne Stroustrup指出的那样充当索引。
是的,但指数相对于什么?指向非虚函数的指针是进程的索引。地址空间。该函数可以在不同的进程中处于不同的地址,因此具有不同的索引。在一个进程中指向给定函数的指针(只是一个内存地址)可能指向另一个进程中完全不同的东西。
指向虚函数的指针是相对于对象地址的偏移,因此给定一个对象(在任何进程中自己的地址空间),你可以找到虚函数通过应用偏移量来获取vtbl条目。对象将位于不同进程中的不同地址(甚至是一个进程中不同实例的不同地址),但vtbl的偏移量是固定的。
换句话说,非虚函数不依赖于对象在内存中的位置。
确切地说,这就是问题所在!它们取决于函数在内存中的位置,这在进程之间不是一成不变的。
我认为只有一个接口(=函数)和许多对象(=可能表示)。
右。
如果指向非虚函数的指针只是成员函数之间的标识符,那么它就无法在进程之间传递和使用。
但他们没有采取行动,就像一个标识符" ......他们是指针。它们是内存中的地址。如果函数在一个进程中的地址为0x12341234,而在另一个进程中的地址为0x00011234,则不能在进程之间传递指针,它不会指向同一个东西!
答案 1 :(得分:1)
非虚函数被称为非成员函数,只有一个额外的隐藏this
参数。指向一个的指针将包含要调用的函数的地址 - 任何额外的间接级别都是不必要的,并且会减慢函数调用并使程序膨胀。
通过在与对象关联的表中查找地址来调用虚函数,该对象的内容取决于动态类型。指向一个的指针将包含该表的索引。它不能存储任何特定函数的地址:它可以引用基类成员,它被不同的派生类重写,因此只有虚拟查找才能知道正确的覆盖。
答案 2 :(得分:1)
在第二个引文中,当他谈到指向成员的指针是偏移时,这不包括指向非虚拟成员函数的指针。这些通常被实现为功能代码的地址,因此它们不太可能在具有其自己的地址空间的另一个进程中工作。
答案 3 :(得分:0)
像Bjarne一样思考。提示,他是表演。他想要他能得到的所有速度。
如果您有非虚方法,则需要立即调用该方法。任何间接都会减慢速度。虚方法内置了一些间接。它需要查找使用this
的特定类型的对象和偏移量,如果不需要,C ++将绕过它。在非虚函数中,它不是必需的,并且为了性能而被跳过。