我听过这个术语,"vtable fixup",用过.这是什么意思?我没有成功问谷歌.我已经知道vtable是什么,所以不需要定义.
我有一个类afporoills,可以帮助我们的内存管理模块中找到数据.(不要问为什么这么奇怪的名字我不知道)
class afporoills{
void** test(int pos);
};
void** afporoills::test(int pos){
int x=(pos<<3)|1023*x;
void** ret=(void**)x;
if((int)ret%16) return this.test(pos+1);
void* (*fp)(float, uint16__t)=x;
ret=ret+(*fp)(1.0f, (uint16__t)pos);
return ret;
}
int test(){
afporoills afporoills14;
return ((char*) (uint32_t) ((uint32_t) (void*) afporoills14.test(((((uint32_t)))((char*) (void*))1));
}
Run Code Online (Sandbox Code Playgroud)
我一直在
[链接器错误]未定义对'vtable for afporoills`的引用
但我不知道vtable是什么!我没用过一个,为什么会有错误呢?
请帮助我,因为如果我没有摆脱那个错误,我不能继续写那个课程.
我还需要做些什么来使test方法完成?
C++规范是否允许非虚拟类的实例包含vtable指针的内存?我问这个,因为一位同事说他曾经使用过C++编译器,其中发生了以下情况:
class MyClass
{
public:
HeaderStruct header; //This had extra words
BodyStruct message_body;
};
Run Code Online (Sandbox Code Playgroud)
然后他将代码更改为此,删除了额外的单词:
struct MyClass
{
HeaderStruct header; //This did not have extra words
BodyStruct message_body;
};
Run Code Online (Sandbox Code Playgroud)
这些类型都不是虚拟的,也不是虚拟的.所以理论上可能这个特定的编译器为类实例分配了vptr的内存,但是没有为struct实例分配内存.所以我只想确定规范是否排除了这种编译器行为.
谢谢!
肯
我在这里检查了最常见的未定义的vtable问题引用,虽然这让我更好地理解了发生了什么,但我仍然无法收集足够的信息来弄清楚为什么我有这个错误.
我有一个简单的Square类,最初我试图从Polygon类继承.由于我对C++已经相对了解并且还在学习,所以我还没有尝试过多态性.
无论如何,在我试图摆脱基类(Polygon)后,我认为这可能会有所帮助.不幸的是,我仍然遇到同样的错误,我不知道发生了什么.我所知道的是,最初,Polygon该类需要一个至少包含构造函数定义的源文件,我给了它.这摆脱vtable了Polygon班级的错误.
我的主要问题是我仍然在为Square类继承这个,它应该从Polygon类继承.我想知道的是我如何正确实现这一点以避免在vtable获得多态性的同时获得错误?
码
Polygon.h /的.cpp
#ifndef POLYGON_H
#define POLYGON_H
#include "Shape.h"
#include "vector3f.h"
class Polygon
{
public:
Polygon();
virtual void Collide(Shape &s) = 0;
virtual void Collide(Polygon &p) = 0;
virtual bool Intersects(const Shape &s) = 0;
virtual bool Intersects(const Polygon &s) = 0;
protected:
virtual void Draw() const = 0;
};
#endif // POLYGON_H
//------------------
#include "Polygon.h" …Run Code Online (Sandbox Code Playgroud) 来自http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/,代码如
class Base
{
public:
virtual void function1() {};
virtual void function2() {};
};
class D1: public Base
{
public:
virtual void function1() {};
};
class D2: public Base
{
public:
virtual void function2() {};
};
Run Code Online (Sandbox Code Playgroud)
生成类似于http://www.learncpp.com/images/CppTutorial/Section12/VTable.gif的虚拟表:

上面的虚拟表是有道理的.所有对象都需要一种方法来调用函数,并且需要使用函数指针来查找它们.
我不明白为什么只有在使用虚拟功能时才需要这个?我肯定遗漏了一些东西,因为虚拟表不直接依赖于虚函数.
例如,如果使用的代码是
class Base
{
public:
void function1() {};
void function2() {};
};
...
Base b;
b.function1();
Run Code Online (Sandbox Code Playgroud)
并且没有虚拟表(意味着没有指向函数所在位置的指针),b.function1()调用将如何解决?
或者在这种情况下我们有一个表,只是它不被称为虚拟表?在这种情况下,会出现一个问题,为什么我们需要一种新的虚函数表?
我刚刚用g ++(4.7)检查了一个包含几十个虚方法的类的大小,因为我听说指针用于虚方法,我认为这将是一个糟糕的实现,因为它会占用80个字节的每个实例在我的系统上只有10个虚拟方法的类.
令我宽慰的是,sizeof(<insert typename here>)只返回了8个字节,即我系统上指针的大小.我认为这意味着它存储了一个指向vtable的指针,而不是每个方法,我只是误解了人们在说什么(或者大多数编译器都是愚蠢的).
然而,在我最终测试之前,我一直在努力使用虚拟方法作为我期望它们工作的方式的指针.我注意到地址实际上是一个相对非常低的数字,通常在100以下,与其他地址相比有8个字节的差异,所以我认为它是某种数组的索引.然后我开始思考如何自己实现vtable,并且不会使用指针,因为我的测试结果清楚地表明了.我很惊讶地发现它使用了整整8个字节(我通过插入一个char字段验证它是否只是填充,后者返回16个字节的sizeof).
相反,我会通过存储一个数组索引(例如4个字节,如果使用具有虚拟方法的65536或更少的类,甚至2个)来实现它,这将在包含指向vtable的指针的查找表中进行搜索,并查找就这样.那么为什么存储指针?出于性能原因,他们只是简单地重用了32位操作系统的代码(因为那里的内存大小没有差别)?
先感谢您.
编辑:
有人要我计算保存的实际内存,我决定编写一个代码示例.不幸的是,它变得非常大(他们要求我在两者中使用10个虚拟方法),但我测试了它,它确实有效.它来了:
#include <cstdio>
#include <cstdlib>
/* For the singleton lovers in this community */
class VirtualTableManager
{
unsigned capacity, count;
void*** vtables;
public:
~VirtualTableManager() {
delete vtables;
}
static VirtualTableManager& getInstance() {
static VirtualTableManager instance;
return instance;
}
unsigned addElement(void** vtable) {
if (count == capacity)
{
vtables = (void***) realloc(vtables, (capacity += 0x2000) * sizeof(void**)); /* Reserves an extra 64KiB of pointers */
}
vtables[count] = vtable;
return …Run Code Online (Sandbox Code Playgroud) 我的问题已经从我发布的另一个问题发生了变化.我开始使用多个文件,并决定将其全部放在一个main.cpp文件中,以便让它正常工作.
main.cpp中:
#include <iostream>
using namespace std;
class arrayListType {
public:
bool isEmpty() ;
bool isFull() ;
int listSize() ;
int maxListSize() ;
void print() ;
bool isItemAtEqual(int location, int item) ;
virtual void insertAt(int location, int insertItem) = 0;
virtual void insertEnd(int insertItem) = 0;
void removeAt(int location);
void retrieveAt(int location, int& retItem) ;
virtual void replaceAt(int location, int repItem) = 0;
void clearList();
virtual int seqSearch(int searchItem) const = 0;
virtual void remove(int removeItem) = 0;
arrayListType (int …Run Code Online (Sandbox Code Playgroud) 在C++中是否可以让多个类共享一个vtable?根据我的理解,如果一个类有一个虚函数,那么它将生成一个vtable.所以每个类都应该有自己的vtable.
我有以下C++代码说明虚拟方法:
class X{
O a;
H b;
virtual void c() = 0;
virtual void d() = 0;
};
class Y : public X{
virtual void c();
virtual void d();
};
Run Code Online (Sandbox Code Playgroud)
在MSVC上输出以下vtable布局:
1> class X size(24):
1> +---
1> 0 | {vfptr}
1> 8 | a
1> 16 | b
1> +---
1>
1> X::$vftable@:
1> | &X_meta
1> | 0
1> 0 | &X::c
1> 1 | &X::d
1>
1> X::c this adjustor: 0
1> X::d this adjustor: 0
1> …Run Code Online (Sandbox Code Playgroud) 假设我有一个名为的共享库libplugin.在这个共享库中,有一个类:
class Plugin
{
public:
virtual void doStuff();
};
Run Code Online (Sandbox Code Playgroud)
我们还假设有另一个名为的共享库libspecialplugin.它包含以下类和函数:
class SpecialPlugin : public Plugin
{
public:
virtual void doStuff();
};
Plugin *createSpecialPlugin()
{
return new SpecialPlugin;
}
Run Code Online (Sandbox Code Playgroud)
现在,假设我更改Plugin并添加以下方法:
virtual void doMoreStuff();
Run Code Online (Sandbox Code Playgroud)
我不重新编译libspecialplugin.
当我这样做时会发生什么:
Plugin *plugin = createSpecialPlugin();
plugin->doMoreStuff();
Run Code Online (Sandbox Code Playgroud)
我猜是发生以下其中一种情况:
Plugin::doMoreStuff()调用该方法该libspecialplugin库是否包含libplugin可用于确定哪些方法被覆盖的信息 - 即使在运行时也是如此?我对这应该发生的事情有点模糊.